summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-01-01 05:24:41 +0100
committerThomas Haller <thaller@redhat.com>2018-01-02 09:57:22 +0100
commitc721d51dc3a94eaae5a02e46fe31b2d5aeb4254d (patch)
treebd84fb29db885cddf6a8eaa81a0a8e0d4e8f48b4
parent60afcc368150570c304f03d8daed4ecb4bcdb48d (diff)
downloadNetworkManager-c721d51dc3a94eaae5a02e46fe31b2d5aeb4254d.tar.gz
systemd: update code from upstream (2018-01-01)
This is a direct dump from systemd git on 2017-01-01, git commit ad552e587f21bf00013d41d48737009a20be6479. ====== SYSTEMD_DIR=../systemd COMMIT=ad552e587f21bf00013d41d48737009a20be6479 ( cd "$SYSTEMD_DIR" git checkout "$COMMIT" git reset --hard git clean -fdx ) git ls-files :/src/systemd/src/ \ :/shared/nm-utils/siphash24.c \ :/shared/nm-utils/siphash24.h \ :/shared/nm-utils/unaligned.h | \ xargs -d '\n' rm -f nm_copy_sd() { mkdir -p "./src/systemd/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/systemd/$1" } nm_copy_sd_shared() { mkdir -p "./shared/nm-utils/" cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}" } nm_copy_sd "src/basic/alloc-util.c" nm_copy_sd "src/basic/alloc-util.h" nm_copy_sd "src/basic/async.h" nm_copy_sd "src/basic/escape.c" nm_copy_sd "src/basic/escape.h" nm_copy_sd "src/basic/ether-addr-util.c" nm_copy_sd "src/basic/ether-addr-util.h" nm_copy_sd "src/basic/extract-word.c" nm_copy_sd "src/basic/extract-word.h" nm_copy_sd "src/basic/fileio.c" nm_copy_sd "src/basic/fileio.h" nm_copy_sd "src/basic/fd-util.c" nm_copy_sd "src/basic/fd-util.h" nm_copy_sd "src/basic/fs-util.c" nm_copy_sd "src/basic/fs-util.h" nm_copy_sd "src/basic/hash-funcs.c" nm_copy_sd "src/basic/hash-funcs.h" nm_copy_sd "src/basic/hashmap.c" nm_copy_sd "src/basic/hashmap.h" nm_copy_sd "src/basic/hexdecoct.c" nm_copy_sd "src/basic/hexdecoct.h" nm_copy_sd "src/basic/hostname-util.c" nm_copy_sd "src/basic/hostname-util.h" nm_copy_sd "src/basic/in-addr-util.c" nm_copy_sd "src/basic/in-addr-util.h" nm_copy_sd "src/basic/io-util.c" nm_copy_sd "src/basic/io-util.h" nm_copy_sd "src/basic/list.h" nm_copy_sd "src/basic/log.h" nm_copy_sd "src/basic/macro.h" nm_copy_sd "src/basic/mempool.h" nm_copy_sd "src/basic/mempool.c" nm_copy_sd "src/basic/parse-util.c" nm_copy_sd "src/basic/parse-util.h" nm_copy_sd "src/basic/path-util.c" nm_copy_sd "src/basic/path-util.h" nm_copy_sd "src/basic/prioq.h" nm_copy_sd "src/basic/prioq.c" nm_copy_sd "src/basic/process-util.h" nm_copy_sd "src/basic/process-util.c" nm_copy_sd "src/basic/random-util.c" nm_copy_sd "src/basic/random-util.h" nm_copy_sd "src/basic/refcnt.h" nm_copy_sd "src/basic/set.h" nm_copy_sd "src/basic/signal-util.h" nm_copy_sd_shared "src/basic/siphash24.c" nm_copy_sd_shared "src/basic/siphash24.h" nm_copy_sd "src/basic/socket-util.c" nm_copy_sd "src/basic/socket-util.h" nm_copy_sd "src/basic/sparse-endian.h" nm_copy_sd "src/basic/stdio-util.h" nm_copy_sd "src/basic/string-table.c" nm_copy_sd "src/basic/string-table.h" nm_copy_sd "src/basic/string-util.c" nm_copy_sd "src/basic/string-util.h" nm_copy_sd "src/basic/strv.c" nm_copy_sd "src/basic/strv.h" nm_copy_sd "src/basic/time-util.c" nm_copy_sd "src/basic/time-util.h" nm_copy_sd "src/basic/umask-util.h" nm_copy_sd_shared "src/basic/unaligned.h" nm_copy_sd "src/basic/utf8.c" nm_copy_sd "src/basic/utf8.h" nm_copy_sd "src/basic/util.c" nm_copy_sd "src/basic/util.h" nm_copy_sd "src/libsystemd-network/arp-util.c" nm_copy_sd "src/libsystemd-network/arp-util.h" nm_copy_sd "src/libsystemd-network/dhcp6-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-network.c" nm_copy_sd "src/libsystemd-network/dhcp6-option.c" nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h" nm_copy_sd "src/libsystemd-network/dhcp-identifier.c" nm_copy_sd "src/libsystemd-network/dhcp-identifier.h" nm_copy_sd "src/libsystemd-network/dhcp-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-network.c" nm_copy_sd "src/libsystemd-network/dhcp-option.c" nm_copy_sd "src/libsystemd-network/dhcp-packet.c" nm_copy_sd "src/libsystemd-network/dhcp-protocol.h" nm_copy_sd "src/libsystemd-network/lldp-internal.h" nm_copy_sd "src/libsystemd-network/lldp-neighbor.c" nm_copy_sd "src/libsystemd-network/lldp-neighbor.h" nm_copy_sd "src/libsystemd-network/lldp-network.c" nm_copy_sd "src/libsystemd-network/lldp-network.h" nm_copy_sd "src/libsystemd-network/network-internal.c" nm_copy_sd "src/libsystemd-network/network-internal.h" nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c" nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c" nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c" nm_copy_sd "src/libsystemd-network/sd-lldp.c" nm_copy_sd "src/libsystemd/sd-event/sd-event.c" nm_copy_sd "src/libsystemd/sd-id128/id128-util.c" nm_copy_sd "src/libsystemd/sd-id128/id128-util.h" nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c" nm_copy_sd "src/shared/dns-domain.c" nm_copy_sd "src/shared/dns-domain.h" nm_copy_sd "src/systemd/_sd-common.h" nm_copy_sd "src/systemd/sd-dhcp6-client.h" nm_copy_sd "src/systemd/sd-dhcp6-lease.h" nm_copy_sd "src/systemd/sd-dhcp-client.h" nm_copy_sd "src/systemd/sd-dhcp-lease.h" nm_copy_sd "src/systemd/sd-event.h" nm_copy_sd "src/systemd/sd-ndisc.h" nm_copy_sd "src/systemd/sd-id128.h" nm_copy_sd "src/systemd/sd-ipv4acd.h" nm_copy_sd "src/systemd/sd-ipv4ll.h" nm_copy_sd "src/systemd/sd-lldp.h"
-rw-r--r--src/systemd/src/basic/async.h2
-rw-r--r--src/systemd/src/basic/fd-util.c25
-rw-r--r--src/systemd/src/basic/fileio.c25
-rw-r--r--src/systemd/src/basic/fs-util.c4
-rw-r--r--src/systemd/src/basic/log.h2
-rw-r--r--src/systemd/src/basic/process-util.c291
-rw-r--r--src/systemd/src/basic/process-util.h20
-rw-r--r--src/systemd/src/basic/socket-util.c24
-rw-r--r--src/systemd/src/basic/socket-util.h3
-rw-r--r--src/systemd/src/basic/string-util.c23
-rw-r--r--src/systemd/src/basic/time-util.c13
-rw-r--r--src/systemd/src/basic/util.c304
-rw-r--r--src/systemd/src/basic/util.h7
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c8
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h3
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c16
16 files changed, 449 insertions, 321 deletions
diff --git a/src/systemd/src/basic/async.h b/src/systemd/src/basic/async.h
index 7eac54d8b2..01c975bb30 100644
--- a/src/systemd/src/basic/async.h
+++ b/src/systemd/src/basic/async.h
@@ -22,5 +22,5 @@
int asynchronous_job(void* (*func)(void *p), void *arg);
-int asynchronous_sync(void);
+int asynchronous_sync(pid_t *ret_pid);
int asynchronous_close(int fd);
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index a0820a9667..404361e8c1 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -192,9 +192,9 @@ int fd_cloexec(int fd, bool cloexec) {
}
void stdio_unset_cloexec(void) {
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
+ (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) {
@@ -227,20 +227,21 @@ int close_all_fds(const int except[], unsigned n_except) {
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+ int q;
if (fd_in_set(fd, except, n_except))
continue;
- if (close_nointr(fd) < 0)
- if (errno != EBADF && r == 0)
- r = -errno;
+ q = close_nointr(fd);
+ if (q < 0 && q != -EBADF && r >= 0)
+ r = q;
}
return r;
}
FOREACH_DIRENT(de, d, return -errno) {
- int fd = -1;
+ int fd = -1, q;
if (safe_atoi(de->d_name, &fd) < 0)
/* Let's better ignore this, just in case */
@@ -255,11 +256,9 @@ int close_all_fds(const int except[], unsigned n_except) {
if (fd_in_set(fd, except, n_except))
continue;
- if (close_nointr(fd) < 0) {
- /* Valgrind has its own FD and doesn't want to have it closed */
- if (errno != EBADF && r == 0)
- r = -errno;
- }
+ q = close_nointr(fd);
+ if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */
+ r = q;
}
return r;
@@ -427,7 +426,7 @@ 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)];
+ 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;
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 3ab50bca2f..71c404bdd0 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -23,6 +23,7 @@
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -64,9 +65,15 @@ int write_string_stream_ts(
assert(f);
assert(line);
- fputs(line, f);
+ if (ferror(f))
+ return -EIO;
+
+ if (fputs(line, f) == EOF)
+ return -errno;
+
if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
- fputc('\n', f);
+ if (fputc('\n', f) == EOF)
+ return -errno;
if (ts) {
struct timespec twice[2] = {*ts, *ts};
@@ -98,6 +105,7 @@ static int write_string_file_atomic(
if (r < 0)
return r;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
r = write_string_stream_ts(f, line, flags, ts);
@@ -167,6 +175,8 @@ int write_string_file_ts(
}
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
setvbuf(f, NULL, _IONBF, 0);
@@ -203,6 +213,8 @@ int read_one_line_file(const char *fn, char **line) {
if (!f)
return -errno;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
r = read_line(f, LONG_LINE_MAX, line);
return r < 0 ? r : 0;
}
@@ -228,6 +240,8 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
if (!f)
return -errno;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
/* We try to read one byte more than we need, so that we know whether we hit eof */
errno = 0;
k = fread(buf, 1, l + accept_extra_nl + 1, f);
@@ -323,6 +337,8 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
if (!f)
return -errno;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
return read_full_stream(f, contents, size);
}
@@ -879,7 +895,8 @@ int write_env_file(const char *fname, char **l) {
if (r < 0)
return r;
- fchmod_umask(fileno(f), 0644);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ (void) fchmod_umask(fileno(f), 0644);
STRV_FOREACH(i, l)
write_env_var(f, *i);
@@ -1461,7 +1478,7 @@ int link_tmpfile(int fd, const char *path, const char *target) {
if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
return -errno;
} else {
- char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+ char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index aa33da48b0..4ca36faf09 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -580,7 +580,7 @@ int tmp_dir(const char **ret) {
}
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
- char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+ char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
int r;
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
@@ -825,7 +825,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
}
int access_fd(int fd, int mode) {
- char p[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+ char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
int r;
/* Like access() but operates on an already open fd */
diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h
index aa5976c3c0..28300312f6 100644
--- a/src/systemd/src/basic/log.h
+++ b/src/systemd/src/basic/log.h
@@ -335,3 +335,5 @@ int log_syntax_internal(
"String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
} \
})
+
+#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG)
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index 5f001494f0..05373689ea 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -26,6 +26,7 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -55,6 +56,7 @@
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
@@ -130,6 +132,8 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
if (max_length == 1) {
/* If there's only room for one byte, return the empty string */
@@ -293,10 +297,17 @@ int rename_process(const char name[]) {
if (isempty(name))
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
+ if (!is_main_thread())
+ return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
+ * cache things without locking, and we make assumptions that PR_SET_NAME sets the
+ * process name that isn't correct on any other threads */
+
l = strlen(name);
- /* First step, change the comm field. */
- (void) prctl(PR_SET_NAME, name);
+ /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
+ * can use PR_SET_NAME, which sets the thread name for the calling thread. */
+ if (prctl(PR_SET_NAME, name) < 0)
+ log_debug_errno(errno, "PR_SET_NAME failed: %m");
if (l > 15) /* Linux process names can be 15 chars at max */
truncated = true;
@@ -406,6 +417,8 @@ int is_kernel_thread(pid_t pid) {
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
count = fread(&c, 1, 1, f);
eof = feof(f);
fclose(f);
@@ -487,6 +500,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
FOREACH_LINE(line, f, return -errno) {
char *l;
@@ -565,6 +580,8 @@ int get_process_environ(pid_t pid, char **env) {
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
while ((c = fgetc(f)) != EOF) {
if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
return -ENOMEM;
@@ -699,6 +716,67 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
return -EPROTO;
}
+/*
+ * Return values:
+ * < 0 : wait_for_terminate_with_timeout() failed to get the state of the
+ * process, the process timed out, the process was terminated by a
+ * signal, or failed for an unknown reason.
+ * >=0 : The process terminated normally with no failures.
+ *
+ * Success is indicated by a return value of zero, a timeout is indicated
+ * by ETIMEDOUT, and all other child failure states are indicated by error
+ * is indicated by a non-zero value.
+ */
+int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
+ sigset_t mask;
+ int r;
+ usec_t until;
+
+ assert_se(sigemptyset(&mask) == 0);
+ assert_se(sigaddset(&mask, SIGCHLD) == 0);
+
+ /* Drop into a sigtimewait-based timeout. Waiting for the
+ * pid to exit. */
+ until = now(CLOCK_MONOTONIC) + timeout;
+ for (;;) {
+ usec_t n;
+ siginfo_t status = {};
+ struct timespec ts;
+
+ n = now(CLOCK_MONOTONIC);
+ if (n >= until)
+ break;
+
+ r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0;
+ /* Assuming we woke due to the child exiting. */
+ if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
+ if (status.si_pid == pid) {
+ /* This is the correct child.*/
+ if (status.si_code == CLD_EXITED)
+ return (status.si_status == 0) ? 0 : -EPROTO;
+ else
+ return -EPROTO;
+ }
+ }
+ /* Not the child, check for errors and proceed appropriately */
+ if (r < 0) {
+ switch (r) {
+ case -EAGAIN:
+ /* Timed out, child is likely hung. */
+ return -ETIMEDOUT;
+ case -EINTR:
+ /* Received a different signal and should retry */
+ continue;
+ default:
+ /* Return any unexpected errors */
+ return r;
+ }
+ }
+ }
+
+ return -EPROTO;
+}
+
void sigkill_wait(pid_t pid) {
assert(pid > 1);
@@ -749,6 +827,8 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
l = strlen(field);
r = 0;
@@ -1062,6 +1142,213 @@ int must_be_root(void) {
return -EPERM;
}
+int safe_fork_full(
+ const char *name,
+ const int except_fds[],
+ size_t n_except_fds,
+ ForkFlags flags,
+ pid_t *ret_pid) {
+
+ pid_t original_pid, pid;
+ sigset_t saved_ss;
+ bool block_signals;
+ int r;
+
+ /* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
+ * returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */
+
+ original_pid = getpid_cached();
+
+ block_signals = flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG);
+
+ if (block_signals) {
+ sigset_t ss;
+
+ /* We temporarily block all signals, so that the new child has them blocked initially. This way, we can be sure
+ * that SIGTERMs are not lost we might send to the child. */
+ if (sigfillset(&ss) < 0)
+ return log_debug_errno(errno, "Failed to reset signal set: %m");
+
+ if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
+ return log_debug_errno(errno, "Failed to reset signal mask: %m");
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ r = -errno;
+
+ if (block_signals) /* undo what we did above */
+ (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
+
+ return log_debug_errno(r, "Failed to fork: %m");
+ }
+ if (pid > 0) {
+ /* We are in the parent process */
+
+ if (block_signals) /* undo what we did above */
+ (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
+
+ log_debug("Sucessfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
+
+ if (ret_pid)
+ *ret_pid = pid;
+
+ return 1;
+ }
+
+ /* We are in the child process */
+
+ if (flags & FORK_REOPEN_LOG) {
+ /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
+ log_close();
+ log_set_open_when_needed(true);
+ }
+
+ if (name) {
+ r = rename_process(name);
+ if (r < 0)
+ log_debug_errno(r, "Failed to rename process, ignoring: %m");
+ }
+
+ if (flags & FORK_DEATHSIG)
+ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) {
+ log_debug_errno(errno, "Failed to set death signal: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (flags & FORK_RESET_SIGNALS) {
+ r = reset_all_signal_handlers();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to reset signal handlers: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ /* This implicitly undoes the signal mask stuff we did before the fork()ing above */
+ r = reset_signal_mask();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to reset signal mask: %m");
+ _exit(EXIT_FAILURE);
+ }
+ } else if (block_signals) { /* undo what we did above */
+ if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
+ log_debug_errno(errno, "Failed to restore signal mask: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (flags & FORK_DEATHSIG) {
+ /* Let's see if the parent PID is still the one we started from? If not, then the parent
+ * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
+
+ if (getppid() != original_pid) {
+ log_debug("Parent died early, raising SIGTERM.");
+ (void) raise(SIGTERM);
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (flags & FORK_CLOSE_ALL_FDS) {
+ /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
+ log_close();
+
+ r = close_all_fds(except_fds, n_except_fds);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to close all file descriptors: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ /* When we were asked to reopen the logs, do so again now */
+ if (flags & FORK_REOPEN_LOG) {
+ log_open();
+ log_set_open_when_needed(false);
+ }
+
+ if (flags & FORK_NULL_STDIO) {
+ r = make_null_stdio();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to connect stdin/stdout to /dev/null: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (ret_pid)
+ *ret_pid = getpid_cached();
+
+ return 0;
+}
+
+int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *ret_pid, const char *path, ...) {
+ bool stdout_is_tty, stderr_is_tty;
+ unsigned n, i;
+ va_list ap;
+ char **l;
+ int r;
+
+ assert(path);
+
+ /* Spawns a temporary TTY agent, making sure it goes away when we go away */
+
+ r = safe_fork_full(name, except, n_except, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, ret_pid);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return 0;
+
+ /* In the child: */
+
+ stdout_is_tty = isatty(STDOUT_FILENO);
+ stderr_is_tty = isatty(STDERR_FILENO);
+
+ if (!stdout_is_tty || !stderr_is_tty) {
+ int fd;
+
+ /* Detach from stdout/stderr. and reopen
+ * /dev/tty for them. This is important to
+ * ensure that when systemctl is started via
+ * popen() or a similar call that expects to
+ * read EOF we actually do generate EOF and
+ * not delay this indefinitely by because we
+ * keep an unused copy of stdin around. */
+ fd = open("/dev/tty", O_WRONLY);
+ if (fd < 0) {
+ log_error_errno(errno, "Failed to open /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
+ log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
+ log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (fd > STDERR_FILENO)
+ close(fd);
+ }
+
+ /* Count arguments */
+ va_start(ap, path);
+ for (n = 0; va_arg(ap, char*); n++)
+ ;
+ va_end(ap);
+
+ /* Allocate strv */
+ l = alloca(sizeof(char *) * (n + 1));
+
+ /* Fill in arguments */
+ va_start(ap, path);
+ for (i = 0; i <= n; i++)
+ l[i] = va_arg(ap, char*);
+ va_end(ap);
+
+ execv(path, l);
+ _exit(EXIT_FAILURE);
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index 39c194df0d..1dd62c6d0a 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -33,6 +33,7 @@
#include "format-util.h"
#include "ioprio.h"
#include "macro.h"
+#include "time-util.h"
#define procfs_file_alloca(pid, field) \
({ \
@@ -41,7 +42,7 @@
if (_pid_ == 0) { \
_r_ = ("/proc/self/" field); \
} else { \
- _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
+ _r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
} \
_r_; \
@@ -61,6 +62,7 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
+int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout);
void sigkill_wait(pid_t pid);
void sigkill_waitp(pid_t *pid);
@@ -140,3 +142,19 @@ int ioprio_parse_priority(const char *s, int *ret);
pid_t getpid_cached(void);
int must_be_root(void);
+
+typedef enum ForkFlags {
+ FORK_RESET_SIGNALS = 1U << 0,
+ FORK_CLOSE_ALL_FDS = 1U << 1,
+ FORK_DEATHSIG = 1U << 2,
+ FORK_NULL_STDIO = 1U << 3,
+ FORK_REOPEN_LOG = 1U << 4,
+} ForkFlags;
+
+int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
+
+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[], unsigned n_except, pid_t *pid, const char *path, ...);
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index b02af357ad..b765fb6125 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -55,6 +55,17 @@
# define IDN_FLAGS 0
#endif
+static const char* const socket_address_type_table[] = {
+ [SOCK_STREAM] = "Stream",
+ [SOCK_DGRAM] = "Datagram",
+ [SOCK_RAW] = "Raw",
+ [SOCK_RDM] = "ReliableDatagram",
+ [SOCK_SEQPACKET] = "SequentialPacket",
+ [SOCK_DCCP] = "DatagramCongestionControl",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
+
int socket_address_parse(SocketAddress *a, const char *s) {
char *e, *n;
unsigned u;
@@ -122,7 +133,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
} else if (startswith(s, "vsock:")) {
/* AF_VSOCK socket in vsock:cid:port notation */
- const char *cid_start = s + strlen("vsock:");
+ const char *cid_start = s + STRLEN("vsock:");
e = strchr(cid_start, ':');
if (!e)
@@ -528,22 +539,25 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
return socket_address_equal(a, &b);
}
-int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
+int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
union sockaddr_union *sa = (union sockaddr_union*) _sa;
+ /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
+
assert(sa);
switch (sa->sa.sa_family) {
+
case AF_INET:
- *port = be16toh(sa->in.sin_port);
+ *ret_port = be16toh(sa->in.sin_port);
return 0;
case AF_INET6:
- *port = be16toh(sa->in6.sin6_port);
+ *ret_port = be16toh(sa->in6.sin6_port);
return 0;
case AF_VSOCK:
- *port = sa->vm.svm_port;
+ *ret_port = sa->vm.svm_port;
return 0;
default:
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index 272e74b0cc..0f84a5e93e 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -72,6 +72,9 @@ typedef enum SocketAddressBindIPv6Only {
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
+const char* socket_address_type_to_string(int t) _const_;
+int socket_address_type_from_string(const char *s) _pure_;
+
int socket_address_parse(SocketAddress *a, const char *s);
int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s);
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index e916000b25..7e2f596edc 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -22,6 +22,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
@@ -669,10 +670,10 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
if (!f)
return NULL;
- /* Note we use the _unlocked() stdio variants on f for performance
- * reasons. It's safe to do so since we created f here and it
- * doesn't leave our scope.
- */
+ /* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here
+ * and it doesn't leave our scope. */
+
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
@@ -684,21 +685,21 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
else if (*i == '\x1B')
state = STATE_ESCAPE;
else if (*i == '\t')
- fputs_unlocked(" ", f);
+ fputs(" ", f);
else
- fputc_unlocked(*i, f);
+ fputc(*i, f);
break;
case STATE_ESCAPE:
if (i >= *ibuf + isz) { /* EOT */
- fputc_unlocked('\x1B', f);
+ fputc('\x1B', f);
break;
} else if (*i == '[') {
state = STATE_BRACKET;
begin = i + 1;
} else {
- fputc_unlocked('\x1B', f);
- fputc_unlocked(*i, f);
+ fputc('\x1B', f);
+ fputc(*i, f);
state = STATE_OTHER;
}
@@ -708,8 +709,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
if (i >= *ibuf + isz || /* EOT */
(!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) {
- fputc_unlocked('\x1B', f);
- fputc_unlocked('[', f);
+ fputc('\x1B', f);
+ fputc('[', f);
state = STATE_OTHER;
i = begin-1;
} else if (*i == 'm')
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index d56576ddbe..95358f8e9f 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -886,8 +886,8 @@ typedef struct ParseTimestampResult {
int parse_timestamp(const char *t, usec_t *usec) {
char *last_space, *tz = NULL;
ParseTimestampResult *shared, tmp;
- int r;
pid_t pid;
+ int r;
last_space = strrchr(t, ' ');
if (last_space != NULL && timezone_is_valid(last_space + 1))
@@ -900,15 +900,12 @@ int parse_timestamp(const char *t, usec_t *usec) {
if (shared == MAP_FAILED)
return negative_errno();
- pid = fork();
-
- if (pid == -1) {
- int fork_errno = errno;
+ r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG, &pid);
+ if (r < 0) {
(void) munmap(shared, sizeof *shared);
- return -fork_errno;
+ return r;
}
-
- if (pid == 0) {
+ if (r == 0) {
bool with_tz = true;
if (setenv("TZ", tz, 1) != 0) {
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index f61d9013e6..2a39ff2b53 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -105,7 +105,7 @@ int socket_from_display(const char *display, char **path) {
k = strspn(display+1, "0123456789");
- f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
+ f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1);
if (!f)
return -ENOMEM;
@@ -118,45 +118,6 @@ int socket_from_display(const char *display, char **path) {
return 0;
}
-int block_get_whole_disk(dev_t d, dev_t *ret) {
- char p[SYS_BLOCK_PATH_MAX("/partition")];
- _cleanup_free_ char *s = NULL;
- int r;
- unsigned n, m;
-
- assert(ret);
-
- /* If it has a queue this is good enough for us */
- xsprintf_sys_block_path(p, "/queue", d);
- if (access(p, F_OK) >= 0) {
- *ret = d;
- return 0;
- }
-
- /* If it is a partition find the originating device */
- xsprintf_sys_block_path(p, "/partition", d);
- if (access(p, F_OK) < 0)
- return -ENOENT;
-
- /* Get parent dev_t */
- xsprintf_sys_block_path(p, "/../dev", d);
- r = read_one_line_file(p, &s);
- if (r < 0)
- return r;
-
- r = sscanf(s, "%u:%u", &m, &n);
- if (r != 2)
- return -EINVAL;
-
- /* Only return this if it is really good enough for us. */
- xsprintf_sys_block_path(p, "/queue", makedev(m, n));
- if (access(p, F_OK) < 0)
- return -ENOENT;
-
- *ret = makedev(m, n);
- return 0;
-}
-
bool kexec_loaded(void) {
_cleanup_free_ char *s = NULL;
@@ -184,112 +145,6 @@ int prot_from_flags(int flags) {
}
}
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
- bool stdout_is_tty, stderr_is_tty;
- pid_t parent_pid, agent_pid;
- sigset_t ss, saved_ss;
- unsigned n, i;
- va_list ap;
- char **l;
-
- assert(pid);
- assert(path);
-
- /* Spawns a temporary TTY agent, making sure it goes away when
- * we go away */
-
- parent_pid = getpid_cached();
-
- /* First we temporarily block all signals, so that the new
- * child has them blocked initially. This way, we can be sure
- * that SIGTERMs are not lost we might send to the agent. */
- assert_se(sigfillset(&ss) >= 0);
- assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
-
- agent_pid = fork();
- if (agent_pid < 0) {
- assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
- return -errno;
- }
-
- if (agent_pid != 0) {
- assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
- *pid = agent_pid;
- return 0;
- }
-
- /* In the child:
- *
- * Make sure the agent goes away when the parent dies */
- if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
- _exit(EXIT_FAILURE);
-
- /* Make sure we actually can kill the agent, if we need to, in
- * case somebody invoked us from a shell script that trapped
- * SIGTERM or so... */
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- /* Check whether our parent died before we were able
- * to set the death signal and unblock the signals */
- if (getppid() != parent_pid)
- _exit(EXIT_SUCCESS);
-
- /* Don't leak fds to the agent */
- close_all_fds(except, n_except);
-
- stdout_is_tty = isatty(STDOUT_FILENO);
- stderr_is_tty = isatty(STDERR_FILENO);
-
- if (!stdout_is_tty || !stderr_is_tty) {
- int fd;
-
- /* Detach from stdout/stderr. and reopen
- * /dev/tty for them. This is important to
- * ensure that when systemctl is started via
- * popen() or a similar call that expects to
- * read EOF we actually do generate EOF and
- * not delay this indefinitely by because we
- * keep an unused copy of stdin around. */
- fd = open("/dev/tty", O_WRONLY);
- if (fd < 0) {
- log_error_errno(errno, "Failed to open /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
- log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
- log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (fd > STDERR_FILENO)
- close(fd);
- }
-
- /* Count arguments */
- va_start(ap, path);
- for (n = 0; va_arg(ap, char*); n++)
- ;
- va_end(ap);
-
- /* Allocate strv */
- l = alloca(sizeof(char *) * (n + 1));
-
- /* Fill in arguments */
- va_start(ap, path);
- for (i = 0; i <= n; i++)
- l[i] = va_arg(ap, char*);
- va_end(ap);
-
- execv(path, l);
- _exit(EXIT_FAILURE);
-}
-
bool in_initrd(void) {
struct statfs s;
@@ -699,131 +554,64 @@ int version(void) {
return 0;
}
-int get_block_device(const char *path, dev_t *dev) {
- struct stat st;
- struct statfs sfs;
-
- assert(path);
- assert(dev);
-
- /* Get's the block device directly backing a file system. If
- * the block device is encrypted, returns the device mapper
- * block device. */
-
- if (lstat(path, &st))
- return -errno;
-
- if (major(st.st_dev) != 0) {
- *dev = st.st_dev;
- return 1;
- }
-
- if (statfs(path, &sfs) < 0)
- return -errno;
-
- if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
- return btrfs_get_block_device(path, dev);
-
- return 0;
+/* This is a direct translation of str_verscmp from boot.c */
+static bool is_digit(int c) {
+ return c >= '0' && c <= '9';
}
-int get_block_device_harder(const char *path, dev_t *dev) {
- _cleanup_closedir_ DIR *d = NULL;
- _cleanup_free_ char *t = NULL;
- char p[SYS_BLOCK_PATH_MAX("/slaves")];
- struct dirent *de, *found = NULL;
- const char *q;
- unsigned maj, min;
- dev_t dt;
- int r;
-
- assert(path);
- assert(dev);
+static int c_order(int c) {
+ if (c == 0 || is_digit(c))
+ return 0;
- /* Gets the backing block device for a file system, and
- * handles LUKS encrypted file systems, looking for its
- * immediate parent, if there is one. */
+ if ((c >= 'a') && (c <= 'z'))
+ return c;
- r = get_block_device(path, &dt);
- if (r <= 0)
- return r;
+ return c + 0x10000;
+}
- xsprintf_sys_block_path(p, "/slaves", dt);
- d = opendir(p);
- if (!d) {
- if (errno == ENOENT)
- goto fallback;
+int str_verscmp(const char *s1, const char *s2) {
+ const char *os1, *os2;
- return -errno;
- }
+ assert(s1);
+ assert(s2);
- FOREACH_DIRENT_ALL(de, d, return -errno) {
+ os1 = s1;
+ os2 = s2;
- if (dot_or_dot_dot(de->d_name))
- continue;
+ while (*s1 || *s2) {
+ int first;
- if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
- continue;
+ while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
+ int order;
- if (found) {
- _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
-
- /* We found a device backed by multiple other devices. We don't really support automatic
- * discovery on such setups, with the exception of dm-verity partitions. In this case there are
- * two backing devices: the data partition and the hash partition. We are fine with such
- * setups, however, only if both partitions are on the same physical device. Hence, let's
- * verify this. */
-
- u = strjoin(p, "/", de->d_name, "/../dev");
- if (!u)
- return -ENOMEM;
-
- v = strjoin(p, "/", found->d_name, "/../dev");
- if (!v)
- return -ENOMEM;
-
- r = read_one_line_file(u, &a);
- if (r < 0) {
- log_debug_errno(r, "Failed to read %s: %m", u);
- goto fallback;
- }
-
- r = read_one_line_file(v, &b);
- if (r < 0) {
- log_debug_errno(r, "Failed to read %s: %m", v);
- goto fallback;
- }
-
- /* Check if the parent device is the same. If not, then the two backing devices are on
- * different physical devices, and we don't support that. */
- if (!streq(a, b))
- goto fallback;
+ order = c_order(*s1) - c_order(*s2);
+ if (order != 0)
+ return order;
+ s1++;
+ s2++;
}
- found = de;
- }
-
- if (!found)
- goto fallback;
-
- q = strjoina(p, "/", found->d_name, "/dev");
-
- r = read_one_line_file(q, &t);
- if (r == -ENOENT)
- goto fallback;
- if (r < 0)
- return r;
-
- if (sscanf(t, "%u:%u", &maj, &min) != 2)
- return -EINVAL;
+ while (*s1 == '0')
+ s1++;
+ while (*s2 == '0')
+ s2++;
+
+ first = 0;
+ while (is_digit(*s1) && is_digit(*s2)) {
+ if (first == 0)
+ first = *s1 - *s2;
+ s1++;
+ s2++;
+ }
- if (maj == 0)
- goto fallback;
+ if (is_digit(*s1))
+ return 1;
+ if (is_digit(*s2))
+ return -1;
- *dev = makedev(maj, min);
- return 1;
+ if (first != 0)
+ return first;
+ }
-fallback:
- *dev = dt;
- return 1;
+ return strcmp(os1, os2);
}
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index a79907de3e..20181ab917 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -71,8 +71,6 @@ bool plymouth_running(void);
bool display_is_local(const char *display) _pure_;
int socket_from_display(const char *display, char **path);
-int block_get_whole_disk(dev_t d, dev_t *ret);
-
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
@@ -86,8 +84,6 @@ bool kexec_loaded(void);
int prot_from_flags(int flags) _const_;
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
-
bool in_initrd(void);
void in_initrd_force(bool value);
@@ -194,5 +190,4 @@ int update_reboot_parameter_and_warn(const char *param);
int version(void);
-int get_block_device(const char *path, dev_t *dev);
-int get_block_device_harder(const char *path, dev_t *dev);
+int str_verscmp(const char *s1, const char *s2);
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index e48b7d22dd..c20e9fca35 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -116,7 +116,8 @@ bool net_match_config(const struct ether_addr *match_mac,
char * const *match_names,
Condition *match_host,
Condition *match_virt,
- Condition *match_kernel,
+ Condition *match_kernel_cmdline,
+ Condition *match_kernel_version,
Condition *match_arch,
const struct ether_addr *dev_mac,
const char *dev_path,
@@ -131,7 +132,10 @@ bool net_match_config(const struct ether_addr *match_mac,
if (match_virt && condition_test(match_virt) <= 0)
return false;
- if (match_kernel && condition_test(match_kernel) <= 0)
+ if (match_kernel_cmdline && condition_test(match_kernel_cmdline) <= 0)
+ return false;
+
+ if (match_kernel_version && condition_test(match_kernel_version) <= 0)
return false;
if (match_arch && condition_test(match_arch) <= 0)
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index a54adac602..4e69f1a598 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -37,7 +37,8 @@ bool net_match_config(const struct ether_addr *match_mac,
char * const *match_name,
Condition *match_host,
Condition *match_virt,
- Condition *match_kernel,
+ Condition *match_kernel_cmdline,
+ Condition *match_kernel_version,
Condition *match_arch,
const struct ether_addr *dev_mac,
const char *dev_path,
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index a186bca38f..78b8e058b4 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -22,6 +22,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
@@ -876,7 +877,8 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
if (r < 0)
goto fail;
- fchmod(fileno(f), 0644);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ (void) fchmod(fileno(f), 0644);
fprintf(f,
"# This is private data. Do not parse.\n");
@@ -923,16 +925,16 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_dns(lease, &addresses);
if (r > 0) {
- fputs_unlocked("DNS=", f);
+ fputs("DNS=", f);
serialize_in_addrs(f, addresses, r);
- fputs_unlocked("\n", f);
+ fputs("\n", f);
}
r = sd_dhcp_lease_get_ntp(lease, &addresses);
if (r > 0) {
- fputs_unlocked("NTP=", f);
+ fputs("NTP=", f);
serialize_in_addrs(f, addresses, r);
- fputs_unlocked("\n", f);
+ fputs("\n", f);
}
r = sd_dhcp_lease_get_domainname(lease, &string);
@@ -941,9 +943,9 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_search_domains(lease, &search_domains);
if (r > 0) {
- fputs_unlocked("DOMAIN_SEARCH_LIST=", f);
+ fputs("DOMAIN_SEARCH_LIST=", f);
fputstrv(f, search_domains, NULL, NULL);
- fputs_unlocked("\n", f);
+ fputs("\n", f);
}
r = sd_dhcp_lease_get_hostname(lease, &string);