diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h
index 02dee37d36..b1e0edbb7f 100644
--- a/src/systemd/src/basic/alloc-util.h
+++ b/src/systemd/src/basic/alloc-util.h
@@ -74,12 +74,14 @@ _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t
return malloc(size * need);
}
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
+#if !HAVE_REALLOCARRAY
+_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) {
if (size_multiply_overflow(size, need))
return NULL;
return realloc(p, size * need);
}
+#endif
_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
if (size_multiply_overflow(size, need))
@@ -128,3 +130,12 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
_new_ = alloca_align(_size_, (align)); \
(void*)memset(_new_, 0, _size_); \
})
+
+/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
+ * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
+#define TAKE_PTR(ptr) \
+ ({ \
+ typeof(ptr) _ptr_ = (ptr); \
+ (ptr) = NULL; \
+ _ptr_; \
+ })
diff --git a/src/systemd/src/basic/extract-word.c b/src/systemd/src/basic/extract-word.c
index 5e42560487..7a6b56f071 100644
--- a/src/systemd/src/basic/extract-word.c
+++ b/src/systemd/src/basic/extract-word.c
@@ -194,8 +194,7 @@ finish:
finish_force_next:
s[sz] = 0;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 1;
}
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index 61a93fcb4a..8bb8c9a629 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -191,12 +191,6 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}
-void stdio_unset_cloexec(void) {
- (void) fd_cloexec(STDIN_FILENO, false);
- (void) fd_cloexec(STDOUT_FILENO, false);
- (void) fd_cloexec(STDERR_FILENO, false);
-}
-
_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
unsigned i;
@@ -367,14 +361,21 @@ bool fdname_is_valid(const char *s) {
}
int fd_get_path(int fd, char **ret) {
- char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int dir = -1;
+ char fdname[DECIMAL_STR_MAX(int)];
int r;
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ 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;
- r = readlink_malloc(procfs_path, ret);
+ xsprintf(fdname, "%i", fd);
- if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+ r = readlinkat_malloc(dir, fdname, ret);
+ if (r == -ENOENT)
+ /* If the file doesn't exist the fd is invalid */
return -EBADF;
return r;
@@ -426,7 +427,6 @@ int move_fd(int from, int to, int cloexec) {
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
- char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
char pattern[] = "/dev/shm/data-fd-XXXXXX";
_cleanup_close_ int fd = -1;
@@ -483,10 +483,7 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags) {
if (r < 0)
return r;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
try_pipe:
@@ -523,10 +520,7 @@ try_pipe:
(void) fd_nonblock(pipefds[0], false);
- r = pipefds[0];
- pipefds[0] = -1;
-
- return r;
+ return TAKE_FD(pipefds[0]);
}
try_dev_shm:
@@ -542,12 +536,7 @@ try_dev_shm:
return -EIO;
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
- r = open(procfs_path, O_RDONLY|O_CLOEXEC);
- if (r < 0)
- return -errno;
-
- return r;
+ return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
}
try_dev_shm_without_o_tmpfile:
@@ -615,3 +604,137 @@ int fd_move_above_stdio(int fd) {
(void) close(fd);
return copy;
}
+
+int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd) {
+
+ int fd[3] = { /* Put together an array of fds we work on */
+ original_input_fd,
+ original_output_fd,
+ original_error_fd
+ };
+
+ int r, i,
+ null_fd = -1, /* if we open /dev/null, we store the fd to it here */
+ copy_fd[3] = { -1, -1, -1 }; /* This contains all fds we duplicate here temporarily, and hence need to close at the end */
+ bool null_readable, null_writable;
+
+ /* Sets up stdin, stdout, stderr with the three file descriptors passed in. If any of the descriptors is
+ * specified as -1 it will be connected with /dev/null instead. If any of the file descriptors is passed as
+ * itself (e.g. stdin as STDIN_FILENO) it is left unmodified, but the O_CLOEXEC bit is turned off should it be
+ * on.
+ *
+ * Note that if any of the passed file descriptors are > 2 they will be closed — both on success and on
+ * failure! Thus, callers should assume that when this function returns the input fds are invalidated.
+ *
+ * Note that when this function fails stdin/stdout/stderr might remain half set up!
+ *
+ * O_CLOEXEC is turned off for all three file descriptors (which is how it should be for
+ * stdin/stdout/stderr). */
+
+ null_readable = original_input_fd < 0;
+ null_writable = original_output_fd < 0 || original_error_fd < 0;
+
+ /* First step, open /dev/null once, if we need it */
+ if (null_readable || null_writable) {
+
+ /* Let's open this with O_CLOEXEC first, and convert it to non-O_CLOEXEC when we move the fd to the final position. */
+ null_fd = open("/dev/null", (null_readable && null_writable ? O_RDWR :
+ null_readable ? O_RDONLY : O_WRONLY) | O_CLOEXEC);
+ if (null_fd < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ /* If this fd is in the 0…2 range, let's move it out of it */
+ if (null_fd < 3) {
+ int copy;
+
+ copy = fcntl(null_fd, F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
+ if (copy < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ safe_close(null_fd);
+ null_fd = copy;
+ }
+ }
+
+ /* Let's assemble fd[] with the fds to install in place of stdin/stdout/stderr */
+ for (i = 0; i < 3; i++) {
+
+ if (fd[i] < 0)
+ fd[i] = null_fd; /* A negative parameter means: connect this one to /dev/null */
+ else if (fd[i] != i && fd[i] < 3) {
+ /* This fd is in the 0…2 territory, but not at its intended place, move it out of there, so that we can work there. */
+ copy_fd[i] = fcntl(fd[i], F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
+ if (copy_fd[i] < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ fd[i] = copy_fd[i];
+ }
+ }
+
+ /* At this point we now have the fds to use in fd[], and they are all above the stdio range, so that we
+ * have freedom to move them around. If the fds already were at the right places then the specific fds are
+ * -1. Let's now move them to the right places. This is the point of no return. */
+ for (i = 0; i < 3; i++) {
+
+ if (fd[i] == i) {
+
+ /* fd is already in place, but let's make sure O_CLOEXEC is off */
+ r = fd_cloexec(i, false);
+ if (r < 0)
+ goto finish;
+
+ } else {
+ assert(fd[i] > 2);
+
+ if (dup2(fd[i], i) < 0) { /* Turns off O_CLOEXEC on the new fd. */
+ r = -errno;
+ goto finish;
+ }
+ }
+ }
+
+ r = 0;
+
+finish:
+ /* Close the original fds, but only if they were outside of the stdio range. Also, properly check for the same
+ * fd passed in multiple times. */
+ safe_close_above_stdio(original_input_fd);
+ if (original_output_fd != original_input_fd)
+ safe_close_above_stdio(original_output_fd);
+ if (original_error_fd != original_input_fd && original_error_fd != original_output_fd)
+ safe_close_above_stdio(original_error_fd);
+
+ /* Close the copies we moved > 2 */
+ for (i = 0; i < 3; i++)
+ safe_close(copy_fd[i]);
+
+ /* Close our null fd, if it's > 2 */
+ safe_close_above_stdio(null_fd);
+
+ return r;
+}
+
+int fd_reopen(int fd, int flags) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ int new_fd;
+
+ /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
+ * turn O_RDWR fds into O_RDONLY fds.
+ *
+ * This doesn't work on sockets (since they cannot be open()ed, ever).
+ *
+ * This implicitly resets the file read index to 0. */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ new_fd = open(procfs_path, flags);
+ if (new_fd < 0)
+ return -errno;
+
+ return new_fd;
+}
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index 284856ae6d..163b096b1a 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -35,6 +35,13 @@ int close_nointr(int fd);
int safe_close(int fd);
void safe_close_pair(int p[]);
+static inline int safe_close_above_stdio(int fd) {
+ if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */
+ return -1;
+
+ return safe_close(fd);
+}
+
void close_many(const int fds[], unsigned n_fd);
int fclose_nointr(FILE *f);
@@ -64,7 +71,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
-void stdio_unset_cloexec(void);
int close_all_fds(const int except[], unsigned n_except);
@@ -93,3 +99,19 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags);
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
int fd_move_above_stdio(int fd);
+
+int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd);
+
+static inline int make_null_stdio(void) {
+ return rearrange_stdio(-1, -1, -1);
+}
+
+/* Like TAKE_PTR() but for file descriptors, resetting them to -1 */
+#define TAKE_FD(fd) \
+ ({ \
+ int _fd_ = (fd); \
+ (fd) = -1; \
+ _fd_; \
+ })
+
+int fd_reopen(int fd, int flags);
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 29b941348a..f807842c31 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -330,8 +330,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
}
buf[l] = 0;
- *contents = buf;
- buf = NULL; /* do not free */
+ *contents = TAKE_PTR(buf);
if (size)
*size = l;
@@ -363,11 +362,11 @@ static int parse_env_file_internal(
void *userdata,
int *n_pushed) {
- _cleanup_free_ char *contents = NULL, *key = NULL;
size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
- char *p, *value = NULL;
- int r;
+ _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL;
unsigned line = 1;
+ char *p;
+ int r;
enum {
PRE_KEY,
@@ -404,10 +403,8 @@ static int parse_env_file_internal(
state = KEY;
last_key_whitespace = (size_t) -1;
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
+ return -ENOMEM;
key[n_key++] = c;
}
@@ -427,10 +424,8 @@ static int parse_env_file_internal(
else if (last_key_whitespace == (size_t) -1)
last_key_whitespace = n_key;
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
+ return -ENOMEM;
key[n_key++] = c;
}
@@ -452,7 +447,7 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
n_key = 0;
value = NULL;
@@ -467,10 +462,8 @@ static int parse_env_file_internal(
else if (!strchr(WHITESPACE, c)) {
state = VALUE;
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -497,7 +490,7 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
n_key = 0;
value = NULL;
@@ -512,10 +505,8 @@ static int parse_env_file_internal(
else if (last_value_whitespace == (size_t) -1)
last_value_whitespace = n_value;
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -527,10 +518,8 @@ static int parse_env_file_internal(
if (!strchr(newline, c)) {
/* Escaped newlines we eat up entirely */
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -542,10 +531,8 @@ static int parse_env_file_internal(
else if (c == '\\')
state = SINGLE_QUOTE_VALUE_ESCAPE;
else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -556,10 +543,8 @@ static int parse_env_file_internal(
state = SINGLE_QUOTE_VALUE;
if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -571,10 +556,8 @@ static int parse_env_file_internal(
else if (c == '\\')
state = DOUBLE_QUOTE_VALUE_ESCAPE;
else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -585,10 +568,8 @@ static int parse_env_file_internal(
state = DOUBLE_QUOTE_VALUE;
if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -633,14 +614,12 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
+
+ value = NULL;
}
return 0;
-
-fail:
- free(value);
- return r;
}
static int check_utf8ness_and_warn(
@@ -1452,8 +1431,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
if (fd < 0)
return -errno;
- *ret_path = tmp;
- tmp = NULL;
+ *ret_path = TAKE_PTR(tmp);
return fd;
}
@@ -1539,8 +1517,7 @@ int read_nul_string(FILE *f, char **ret) {
return -ENOMEM;
}
- *ret = x;
- x = NULL;
+ *ret = TAKE_PTR(x);
return 0;
}
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 85c8070a1b..112aedd027 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -458,10 +458,8 @@ int get_files_in_directory(const char *path, char ***list) {
n++;
}
- if (list) {
- *list = l;
- l = NULL; /* avoid freeing */
- }
+ if (list)
+ *list = TAKE_PTR(l);
return n;
}
@@ -579,6 +577,10 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
return r;
}
+static bool noop_root(const char *root) {
+ return isempty(root) || path_equal(root, "/");
+}
+
static bool safe_transition(const struct stat *a, const struct stat *b) {
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
@@ -629,9 +631,19 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* specified path. */
/* A root directory of "/" or "" is identical to none */
- if (isempty(original_root) || path_equal(original_root, "/"))
+ if (noop_root(original_root))
original_root = NULL;
+ if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN)) == CHASE_OPEN) {
+ /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
+ * and doesn't care about any of the other special features we provide either. */
+ r = open(path, O_PATH|O_CLOEXEC);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
+
if (original_root) {
r = path_make_absolute_cwd(original_root, &root);
if (r < 0)
@@ -685,8 +697,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
/* Just a single slash? Then we reached the end. */
if (path_equal(first, "/")) {
/* Preserve the trailing slash */
- if (!strextend(&done, "/", NULL))
- return -ENOMEM;
+
+ if (flags & CHASE_TRAIL_SLASH)
+ if (!strextend(&done, "/", NULL))
+ return -ENOMEM;
break;
}
@@ -732,8 +746,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
}
safe_close(fd);
- fd = fd_parent;
- fd_parent = -1;
+ fd = TAKE_FD(fd_parent);
continue;
}
@@ -838,10 +851,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
}
/* If this is not a symlink, then let's just add the name we read to what we already verified. */
- if (!done) {
- done = first;
- first = NULL;
- } else {
+ if (!done)
+ done = TAKE_PTR(first);
+ else {
/* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
if (streq(done, "/"))
*done = '\0';
@@ -852,8 +864,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
/* And iterate again, but go one directory further down. */
safe_close(fd);
- fd = child;
- child = -1;
+ fd = TAKE_FD(child);
}
if (!done) {
@@ -863,27 +874,100 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM;
}
- if (ret) {
- *ret = done;
- done = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(done);
if (flags & CHASE_OPEN) {
- int q;
-
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
* opening /proc/self/fd/xyz. */
assert(fd >= 0);
- q = fd;
- fd = -1;
-
- return q;
+ return TAKE_FD(fd);
}
return exists;
}
+int chase_symlinks_and_open(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ int open_flags,
+ char **ret_path) {
+
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (noop_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ r = open(path, open_flags);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ r = fd_reopen(path_fd, open_flags);
+ if (r < 0)
+ return r;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ return r;
+}
+
+int chase_symlinks_and_opendir(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ char **ret_path,
+ DIR **ret_dir) {
+
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ DIR *d;
+
+ if (!ret_dir)
+ return -EINVAL;
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (noop_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ d = opendir(path);
+ if (!d)
+ return -errno;
+
+ *ret_dir = d;
+ return 0;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", path_fd);
+ d = opendir(procfs_path);
+ if (!d)
+ return -errno;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ *ret_dir = d;
+ return 0;
+}
+
int access_fd(int fd, int mode) {
char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
int r;
@@ -891,10 +975,9 @@ int access_fd(int fd, int mode) {
/* Like access() but operates on an already open fd */
xsprintf(p, "/proc/self/fd/%i", fd);
-
r = access(p, mode);
if (r < 0)
- r = -errno;
+ return -errno;
return r;
}
@@ -978,8 +1061,19 @@ int fsync_directory_of_file(int fd) {
return r;
r = fd_get_path(fd, &path);
- if (r < 0)
+ if (r < 0) {
+ log_debug("Failed to query /proc/self/fd/%d%s: %m",
+ fd,
+ r == -EOPNOTSUPP ? ", ignoring" : "");
+
+ if (r == -EOPNOTSUPP)
+ /* If /proc is not available, we're most likely running in some
+ * chroot environment, and syncing the directory is not very
+ * important in that case. Let's just silently do nothing. */
+ return 0;
+
return r;
+ }
if (!path_is_absolute(path))
return -EINVAL;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 82d7e765b3..2225b7e74b 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -20,6 +20,7 @@
along with systemd; If not, see .
***/
+#include
#include
#include
#include
@@ -86,10 +87,14 @@ enum {
CHASE_NO_AUTOFS = 1U << 2, /* If set, return -EREMOTE if autofs mount point found */
CHASE_SAFE = 1U << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_OPEN = 1U << 4, /* If set, return an O_PATH object to the final component */
+ CHASE_TRAIL_SLASH = 1U << 5, /* If set, any trailing slash will be preserved */
};
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
+int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path);
+int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir);
+
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
PROTECT_ERRNO;
diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c
index fe7e4954ef..0764521b6f 100644
--- a/src/systemd/src/basic/hexdecoct.c
+++ b/src/systemd/src/basic/hexdecoct.c
@@ -583,7 +583,7 @@ static int base64_append_width(
if (len <= 0)
return len;
- lines = (len + width - 1) / width;
+ lines = DIV_ROUND_UP(len, width);
slen = strlen_ptr(sep);
t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h
index 5b5a25bd6d..314be128a2 100644
--- a/src/systemd/src/basic/log.h
+++ b/src/systemd/src/basic/log.h
@@ -144,19 +144,6 @@ int log_object_internal(
const char *extra,
const char *format, ...) _printf_(10,11);
-int log_object_internalv(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *format,
- va_list ap) _printf_(10,0);
-
int log_struct_internal(
int level,
int error,
@@ -199,7 +186,7 @@ int log_dump_internal(
char *buffer);
/* Logging for various assertions */
-noreturn void log_assert_failed_realm(
+_noreturn_ void log_assert_failed_realm(
LogRealm realm,
const char *text,
const char *file,
@@ -208,7 +195,7 @@ noreturn void log_assert_failed_realm(
#define log_assert_failed(text, ...) \
log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__)
-noreturn void log_assert_failed_unreachable_realm(
+_noreturn_ void log_assert_failed_unreachable_realm(
LogRealm realm,
const char *text,
const char *file,
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index 89bdd852a9..8e61ff0685 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -53,6 +53,26 @@
#else
#define _fallthrough_
#endif
+/* Define C11 noreturn without and even on older gcc
+ * compiler versions */
+#ifndef _noreturn_
+#if __STDC_VERSION__ >= 201112L
+#define _noreturn_ _Noreturn
+#else
+#define _noreturn_ __attribute__((noreturn))
+#endif
+#endif
+
+#if !defined(HAS_FEATURE_MEMORY_SANITIZER)
+# if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+# define HAS_FEATURE_MEMORY_SANITIZER 1
+# endif
+# endif
+# if !defined(HAS_FEATURE_MEMORY_SANITIZER)
+# define HAS_FEATURE_MEMORY_SANITIZER 0
+# endif
+#endif
/* Temporarily disable some warnings */
#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
@@ -414,21 +434,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#endif
#endif
-/* Define C11 noreturn without and even on older gcc
- * compiler versions */
-#ifndef noreturn
-#if __STDC_VERSION__ >= 201112L
-#define noreturn _Noreturn
-#else
-#define noreturn __attribute__((noreturn))
-#endif
-#endif
-
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
func(*p); \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#include "log.h"
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index fa5b4a353a..eacd5ba360 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -324,8 +324,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
return -EINVAL;
*error = e;
- *name = n;
- n = NULL;
+ *name = TAKE_PTR(n);
return 0;
}
@@ -371,12 +370,13 @@ finish:
}
-int safe_atou(const char *s, unsigned *ret_u) {
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret_u);
+ assert(base <= 16);
/* strtoul() is happy to parse negative values, and silently
* converts them to unsigned values without generating an
@@ -389,7 +389,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
s += strspn(s, WHITESPACE);
errno = 0;
- l = strtoul(s, &x, 0);
+ l = strtoul(s, &x, base);
if (errno > 0)
return -errno;
if (!x || x == s || *x != 0)
@@ -487,17 +487,18 @@ int safe_atou8(const char *s, uint8_t *ret) {
return 0;
}
-int safe_atou16(const char *s, uint16_t *ret) {
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret);
+ assert(base <= 16);
s += strspn(s, WHITESPACE);
errno = 0;
- l = strtoul(s, &x, 0);
+ l = strtoul(s, &x, base);
if (errno > 0)
return -errno;
if (!x || x == s || *x != 0)
@@ -531,30 +532,6 @@ int safe_atoi16(const char *s, int16_t *ret) {
return 0;
}
-int safe_atoux16(const char *s, uint16_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret);
-
- s += strspn(s, WHITESPACE);
-
- errno = 0;
- l = strtoul(s, &x, 16);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x != 0)
- return -EINVAL;
- if (s[0] == '-')
- return -ERANGE;
- if ((unsigned long) (uint16_t) l != l)
- return -ERANGE;
-
- *ret = (uint16_t) l;
- return 0;
-}
-
int safe_atod(const char *s, double *ret_d) {
_cleanup_(freelocalep) locale_t loc = (locale_t) 0;
char *x = NULL;
diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h
index 727422056a..1605cc4ff5 100644
--- a/src/systemd/src/basic/parse-util.h
+++ b/src/systemd/src/basic/parse-util.h
@@ -44,17 +44,29 @@ int parse_syscall_and_errno(const char *in, char **name, int *error);
#define FORMAT_BYTES_MAX 8
char *format_bytes(char *buf, size_t l, uint64_t t);
-int safe_atou(const char *s, unsigned *ret_u);
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u);
+
+static inline int safe_atou(const char *s, unsigned *ret_u) {
+ return safe_atou_full(s, 0, ret_u);
+}
+
int safe_atoi(const char *s, int *ret_i);
int safe_atollu(const char *s, unsigned long long *ret_u);
int safe_atolli(const char *s, long long int *ret_i);
int safe_atou8(const char *s, uint8_t *ret);
-int safe_atou16(const char *s, uint16_t *ret);
-int safe_atoi16(const char *s, int16_t *ret);
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret);
-int safe_atoux16(const char *s, uint16_t *ret);
+static inline int safe_atou16(const char *s, uint16_t *ret) {
+ return safe_atou16_full(s, 0, ret);
+}
+
+static inline int safe_atoux16(const char *s, uint16_t *ret) {
+ return safe_atou16_full(s, 16, ret);
+}
+
+int safe_atoi16(const char *s, int16_t *ret);
static inline int safe_atou32(const char *s, uint32_t *ret_u) {
assert_cc(sizeof(uint32_t) == sizeof(unsigned));
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index df94629385..d4c4a02cb3 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -290,8 +290,7 @@ char **path_strv_resolve(char **l, const char *root) {
r = chase_symlinks(t, root, 0, &u);
if (r == -ENOENT) {
if (root) {
- u = orig;
- orig = NULL;
+ u = TAKE_PTR(orig);
free(t);
} else
u = t;
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 89c285e076..73f1769fd9 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -28,8 +28,14 @@
#include "string-util.h"
#include "time-util.h"
-#define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
-#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":/sbin:/bin"
+#if HAVE_SPLIT_BIN
+# define PATH_SBIN_BIN(x) x "sbin:" x "bin"
+#else
+# define PATH_SBIN_BIN(x) x "bin"
+#endif
+
+#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
+#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
#if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
diff --git a/src/systemd/src/basic/prioq.c b/src/systemd/src/basic/prioq.c
index 407b17e9bf..2a1f1af878 100644
--- a/src/systemd/src/basic/prioq.c
+++ b/src/systemd/src/basic/prioq.c
@@ -173,7 +173,7 @@ int prioq_put(Prioq *q, void *data, unsigned *idx) {
struct prioq_item *j;
n = MAX((q->n_items+1) * 2, 16u);
- j = realloc(q->items, sizeof(struct prioq_item) * n);
+ j = reallocarray(q->items, n, sizeof(struct prioq_item));
if (!j)
return -ENOMEM;
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index aa41b3b686..2583b310a4 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -623,8 +623,7 @@ int get_process_environ(pid_t pid, char **env) {
} else
outcome[sz] = '\0';
- *env = outcome;
- outcome = NULL;
+ *env = TAKE_PTR(outcome);
return 0;
}
@@ -987,7 +986,7 @@ bool is_main_thread(void) {
return cached > 0;
}
-noreturn void freeze(void) {
+_noreturn_ void freeze(void) {
log_close();
@@ -1166,6 +1165,7 @@ extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void
extern void* __dso_handle __attribute__ ((__weak__));
pid_t getpid_cached(void) {
+ static bool installed = false;
pid_t current_value;
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
@@ -1186,10 +1186,18 @@ pid_t getpid_cached(void) {
new_pid = raw_getpid();
- if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) {
- /* OOM? Let's try again later */
- cached_pid = CACHED_PID_UNSET;
- return new_pid;
+ if (!installed) {
+ /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
+ * only half-documented (glibc doesn't document it but LSB does — though only superficially)
+ * we'll check for errors only in the most generic fashion possible. */
+
+ if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) {
+ /* OOM? Let's try again later */
+ cached_pid = CACHED_PID_UNSET;
+ return new_pid;
+ }
+
+ installed = true;
}
cached_pid = new_pid;
@@ -1428,8 +1436,7 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
_exit(EXIT_FAILURE);
}
- if (fd > STDERR_FILENO)
- close(fd);
+ safe_close_above_stdio(fd);
}
/* Count arguments */
@@ -1458,7 +1465,7 @@ static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_IDLE] = "idle"
};
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES);
static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited",
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index 93029e36e5..5170adec7b 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -91,7 +91,7 @@ int pid_from_same_root_fs(pid_t pid);
bool is_main_thread(void);
-noreturn void freeze(void);
+_noreturn_ void freeze(void);
bool oom_score_adjust_is_valid(int oa);
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index b91b093132..fd26ae7137 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -985,8 +985,7 @@ int getpeersec(int fd, char **ret) {
if (isempty(s))
return -EOPNOTSUPP;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
diff --git a/src/systemd/src/basic/stdio-util.h b/src/systemd/src/basic/stdio-util.h
index dbfafba269..d3fed365d8 100644
--- a/src/systemd/src/basic/stdio-util.h
+++ b/src/systemd/src/basic/stdio-util.h
@@ -27,9 +27,11 @@
#include "macro.h"
-#define xsprintf(buf, fmt, ...) \
- assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough")
+#define snprintf_ok(buf, len, fmt, ...) \
+ ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len))
+#define xsprintf(buf, fmt, ...) \
+ assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__), "xsprintf: " #buf "[] must be big enough")
#define VA_FORMAT_ADVANCE(format, ap) \
do { \
diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h
index 4306b90f46..e78a6dbdef 100644
--- a/src/systemd/src/basic/string-table.h
+++ b/src/systemd/src/basic/string-table.h
@@ -93,13 +93,11 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
@@ -111,8 +109,7 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
/* For string conversions where numbers are also acceptable */
#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index 68e2e874b4..8010016451 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -214,7 +214,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
p = strv_length(*a);
q = strv_length(b);
- t = realloc(*a, sizeof(char*) * (p + q + 1));
+ t = reallocarray(*a, p + q + 1, sizeof(char *));
if (!t)
return -ENOMEM;
@@ -341,8 +341,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
if (!GREEDY_REALLOC(l, allocated, n + 2))
return -ENOMEM;
- l[n++] = word;
- word = NULL;
+ l[n++] = TAKE_PTR(word);
l[n] = NULL;
}
@@ -353,8 +352,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
return -ENOMEM;
}
- *t = l;
- l = NULL;
+ *t = TAKE_PTR(l);
return (int) n;
}
@@ -407,7 +405,7 @@ int strv_push(char ***l, char *value) {
if (m < n)
return -ENOMEM;
- c = realloc_multiply(*l, sizeof(char*), m);
+ c = reallocarray(*l, m, sizeof(char*));
if (!c)
return -ENOMEM;
@@ -432,7 +430,7 @@ int strv_push_pair(char ***l, char *a, char *b) {
if (m < n)
return -ENOMEM;
- c = realloc_multiply(*l, sizeof(char*), m);
+ c = reallocarray(*l, m, sizeof(char*));
if (!c)
return -ENOMEM;
@@ -546,7 +544,7 @@ int strv_extend_front(char ***l, const char *value) {
if (!v)
return -ENOMEM;
- c = realloc_multiply(*l, sizeof(char*), m);
+ c = reallocarray(*l, m, sizeof(char*));
if (!c) {
free(v);
return -ENOMEM;
@@ -861,7 +859,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
k = strv_length(*l);
- nl = realloc(*l, sizeof(char*) * (k + n + 1));
+ nl = reallocarray(*l, k + n + 1, sizeof(char *));
if (!nl)
return -ENOMEM;
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 7863a14fb2..b0303a17fa 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -181,11 +181,13 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
const void *p;
int comparison;
+ assert(!size_multiply_overflow(nmemb, size));
+
l = 0;
u = nmemb;
while (l < u) {
idx = (l + u) / 2;
- p = (const char *) base + idx * size;
+ p = (const uint8_t*) base + idx * size;
comparison = compar(key, p, arg);
if (comparison < 0)
u = idx;
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 6f8d8bef34..19e9eae126 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -91,6 +91,19 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar) (const void *, const void *, void *),
void *arg);
+/**
+ * Normal bsearch requires base to be nonnull. Here were require
+ * that only if nmemb > 0.
+ */
+static inline void* bsearch_safe(const void *key, const void *base,
+ size_t nmemb, size_t size, comparison_fn_t compar) {
+ if (nmemb <= 0)
+ return NULL;
+
+ assert(base);
+ return bsearch(key, base, nmemb, size, compar);
+}
+
/**
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c
index b8e9b2e496..3217ac0d1f 100644
--- a/src/systemd/src/libsystemd-network/arp-util.c
+++ b/src/systemd/src/libsystemd-network/arp-util.c
@@ -103,10 +103,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
if (r < 0)
return -errno;
- r = s;
- s = -1;
-
- return r;
+ return TAKE_FD(s);
}
static int arp_send_packet(int fd, int ifindex,
diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c
index 602bf08a60..ac9a7a31b6 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -123,10 +123,7 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
if (r < 0)
return -errno;
- r = s;
- s = -1;
-
- return r;
+ return TAKE_FD(s);
}
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
@@ -211,10 +208,7 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
if (r < 0)
return -errno;
- r = s;
- s = -1;
-
- return r;
+ return TAKE_FD(s);
}
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c
index 0489579e7f..142e39bc66 100644
--- a/src/systemd/src/libsystemd-network/dhcp-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp-option.c
@@ -253,10 +253,8 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c
if (message_type == 0)
return -ENOMSG;
- if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) {
- *_error_message = error_message;
- error_message = NULL;
- }
+ if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE))
+ *_error_message = TAKE_PTR(error_message);
return message_type;
}
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index b3b8fddbcb..70f5909304 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -67,9 +67,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
if (r < 0)
return -errno;
- r = s;
- s = -1;
- return r;
+ return TAKE_FD(s);
}
int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index df96ad739d..2b3c8ceb59 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -617,8 +617,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
idx++;
}
- *str_arr = names;
- names = NULL;
+ *str_arr = TAKE_PTR(names);
return idx;
diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c
index cb3841ef22..c653813cfb 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.c
+++ b/src/systemd/src/libsystemd-network/lldp-network.c
@@ -92,8 +92,5 @@ int lldp_network_bind_raw_socket(int ifindex) {
if (r < 0)
return -errno;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index 94386e4860..00a56c8206 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -276,10 +276,9 @@ int config_parse_ifalias(const char *unit,
}
free(*s);
- if (*n) {
- *s = n;
- n = NULL;
- } else
+ if (*n)
+ *s = TAKE_PTR(n);
+ else
*s = NULL;
return 0;
@@ -424,7 +423,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
if (r == 0)
break;
- new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
+ new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr));
if (!new_addresses)
return -ENOMEM;
else
@@ -437,8 +436,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
size++;
}
- *ret = addresses;
- addresses = NULL;
+ *ret = TAKE_PTR(addresses);
return size;
}
@@ -478,7 +476,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
if (r == 0)
break;
- new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
+ new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr));
if (!new_addresses)
return -ENOMEM;
else
@@ -491,8 +489,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
size++;
}
- *ret = addresses;
- addresses = NULL;
+ *ret = TAKE_PTR(addresses);
return size;
}
@@ -585,8 +582,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
*ret_size = size;
*ret_allocated = allocated;
- *ret = routes;
- routes = NULL;
+ *ret = TAKE_PTR(routes);
return 0;
}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 33f3469f07..9cf49747e0 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -354,9 +354,10 @@ int sd_dhcp_client_set_client_id(
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
-int sd_dhcp_client_set_iaid_duid(
+static int dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
uint32_t iaid,
+ bool append_iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
@@ -377,15 +378,17 @@ int sd_dhcp_client_set_iaid_duid(
zero(client->client_id);
client->client_id.type = 255;
- /* If IAID is not configured, generate it. */
- if (iaid == 0) {
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
- client->mac_addr_len,
- &client->client_id.ns.iaid);
- if (r < 0)
- return r;
- } else
- client->client_id.ns.iaid = htobe32(iaid);
+ if (append_iaid) {
+ /* If IAID is not configured, generate it. */
+ if (iaid == 0) {
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
+ client->mac_addr_len,
+ &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+ } else
+ client->client_id.ns.iaid = htobe32(iaid);
+ }
if (duid != NULL) {
client->client_id.ns.duid.type = htobe16(duid_type);
@@ -399,7 +402,7 @@ int sd_dhcp_client_set_iaid_duid(
return -EOPNOTSUPP;
client->client_id_len = sizeof(client->client_id.type) + len +
- sizeof(client->client_id.ns.iaid);
+ (append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured IAID+DUID, restarting.");
@@ -410,6 +413,23 @@ int sd_dhcp_client_set_iaid_duid(
return 0;
}
+int sd_dhcp_client_set_iaid_duid(
+ sd_dhcp_client *client,
+ uint32_t iaid,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len);
+}
+
+int sd_dhcp_client_set_duid(
+ sd_dhcp_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len);
+}
+
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname) {
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 2e88e39878..9db0a93898 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -807,8 +807,7 @@ int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***d
pos = next_chunk;
}
- *domains = names;
- names = NULL;
+ *domains = TAKE_PTR(names);
return cnt;
}
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index 8c807e0e23..89d18431e4 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -295,8 +295,7 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) {
if (r < 0)
return r;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return r;
}
@@ -601,8 +600,7 @@ int dns_name_endswith(const char *name, const char *suffix) {
/* Not the same, let's jump back, and try with the next label again */
s = suffix;
- n = saved_n;
- saved_n = NULL;
+ n = TAKE_PTR(saved_n);
}
}
}
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index 6eb9eb61a8..789cc50174 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -132,6 +132,11 @@ int sd_dhcp_client_set_iaid_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len);
+int sd_dhcp_client_set_duid(
+ sd_dhcp_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len);
int sd_dhcp_client_get_client_id(
sd_dhcp_client *client,
uint8_t *type,