diff options
Diffstat (limited to 'src')
52 files changed, 770 insertions, 404 deletions
diff --git a/src/basic/def.h b/src/basic/def.h index 011c7c667e..5aaba1fe87 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -63,13 +63,7 @@ #define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket" #define KERNEL_SYSTEM_BUS_ADDRESS "kernel:path=/sys/fs/kdbus/0-system/bus" - -#ifdef ENABLE_KDBUS -# define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS -#else -# define DEFAULT_SYSTEM_BUS_ADDRESS UNIX_SYSTEM_BUS_ADDRESS -#endif - +#define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS #define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus" #define KERNEL_USER_BUS_ADDRESS_FMT "kernel:path=/sys/fs/kdbus/"UID_FMT"-user/bus" diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c index c09efdd2cb..5ab36825c0 100644 --- a/src/basic/exit-status.c +++ b/src/basic/exit-status.c @@ -20,6 +20,7 @@ ***/ #include <stdlib.h> +#include <signal.h> #include "exit-status.h" #include "set.h" diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 0ee2f3bd31..e5f05f36f8 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1798,8 +1798,6 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { struct ordered_hashmap_entry *e; unsigned hash, idx; - assert(key); - if (!h) return NULL; diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 5723f09ca9..2af23024de 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -65,7 +65,6 @@ typedef struct { } Iterator; #define _IDX_ITERATOR_FIRST (UINT_MAX - 1) -#define _IDX_ITERATOR_NIL (UINT_MAX) #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]); diff --git a/src/basic/macro.h b/src/basic/macro.h index cc1c9e73c0..5fa17ed208 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -248,18 +248,19 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { REENABLE_WARNING #endif +#define assert_log(expr) ((_likely_(expr)) \ + ? (true) \ + : (log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) + #define assert_return(expr, r) \ do { \ - if (_unlikely_(!(expr))) { \ - log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + if (!assert_log(expr)) \ return (r); \ - } \ } while (false) #define assert_return_errno(expr, r, err) \ do { \ - if (_unlikely_(!(expr))) { \ - log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + if (!assert_log(expr)) { \ errno = err; \ return (r); \ } \ diff --git a/src/basic/util.c b/src/basic/util.c index b7c70af541..727be56f58 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -60,8 +60,8 @@ #include <linux/fs.h> /* When we include libgen.h because we need dirname() we immediately - * undefine basename() since libgen.h defines it as a macro to the XDG - * version which is really broken. */ + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ #include <libgen.h> #undef basename @@ -5209,35 +5209,6 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { break; - case VALUE_ESCAPE: - if (c == 0) { - if (flags & UNQUOTE_RELAX) - goto finish; - return -EINVAL; - } - - if (!GREEDY_REALLOC(s, allocated, sz+7)) - return -ENOMEM; - - if (flags & UNQUOTE_CUNESCAPE) { - uint32_t u; - - r = cunescape_one(*p, (size_t) -1, &c, &u); - if (r < 0) - return -EINVAL; - - (*p) += r - 1; - - if (c != 0) - s[sz++] = c; /* normal explicit char */ - else - sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */ - } else - s[sz++] = c; - - state = VALUE; - break; - case SINGLE_QUOTE: if (c == 0) { if (flags & UNQUOTE_RELAX) @@ -5256,35 +5227,6 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { break; - case SINGLE_QUOTE_ESCAPE: - if (c == 0) { - if (flags & UNQUOTE_RELAX) - goto finish; - return -EINVAL; - } - - if (!GREEDY_REALLOC(s, allocated, sz+7)) - return -ENOMEM; - - if (flags & UNQUOTE_CUNESCAPE) { - uint32_t u; - - r = cunescape_one(*p, (size_t) -1, &c, &u); - if (r < 0) - return -EINVAL; - - (*p) += r - 1; - - if (c != 0) - s[sz++] = c; - else - sz += utf8_encode_unichar(s + sz, u); - } else - s[sz++] = c; - - state = SINGLE_QUOTE; - break; - case DOUBLE_QUOTE: if (c == 0) return -EINVAL; @@ -5301,33 +5243,56 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) { break; + case SINGLE_QUOTE_ESCAPE: case DOUBLE_QUOTE_ESCAPE: + case VALUE_ESCAPE: + if (!GREEDY_REALLOC(s, allocated, sz+7)) + return -ENOMEM; + if (c == 0) { + if ((flags & UNQUOTE_CUNESCAPE_RELAX) && + (state == VALUE_ESCAPE || flags & UNQUOTE_RELAX)) { + /* If we find an unquoted trailing backslash and we're in + * UNQUOTE_CUNESCAPE_RELAX mode, keep it verbatim in the + * output. + * + * Unbalanced quotes will only be allowed in UNQUOTE_RELAX + * mode, UNQUOTE_CUNESCAP_RELAX mode does not allow them. + */ + s[sz++] = '\\'; + goto finish; + } if (flags & UNQUOTE_RELAX) goto finish; return -EINVAL; } - if (!GREEDY_REALLOC(s, allocated, sz+7)) - return -ENOMEM; - if (flags & UNQUOTE_CUNESCAPE) { uint32_t u; r = cunescape_one(*p, (size_t) -1, &c, &u); - if (r < 0) + if (r < 0) { + if (flags & UNQUOTE_CUNESCAPE_RELAX) { + s[sz++] = '\\'; + s[sz++] = c; + goto end_escape; + } return -EINVAL; + } (*p) += r - 1; if (c != 0) - s[sz++] = c; + s[sz++] = c; /* normal explicit char */ else - sz += utf8_encode_unichar(s + sz, u); + sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */ } else s[sz++] = c; - state = DOUBLE_QUOTE; +end_escape: + state = (state == SINGLE_QUOTE_ESCAPE) ? SINGLE_QUOTE : + (state == DOUBLE_QUOTE_ESCAPE) ? DOUBLE_QUOTE : + VALUE; break; case SPACE: @@ -5355,6 +5320,36 @@ finish: return 1; } +int unquote_first_word_and_warn( + const char **p, + char **ret, + UnquoteFlags flags, + const char *unit, + const char *filename, + unsigned line, + const char *rvalue) { + /* Try to unquote it, if it fails, warn about it and try again but this + * time using UNQUOTE_CUNESCAPE_RELAX to keep the backslashes verbatim + * in invalid escape sequences. */ + const char *save; + int r; + + save = *p; + r = unquote_first_word(p, ret, flags); + if (r < 0 && !(flags&UNQUOTE_CUNESCAPE_RELAX)) { + /* Retry it with UNQUOTE_CUNESCAPE_RELAX. */ + *p = save; + r = unquote_first_word(p, ret, flags|UNQUOTE_CUNESCAPE_RELAX); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Unbalanced quoting in command line, ignoring: \"%s\"", rvalue); + else + log_syntax(unit, LOG_WARNING, filename, line, EINVAL, + "Invalid escape sequences in command line: \"%s\"", rvalue); + } + return r; +} + int unquote_many_words(const char **p, UnquoteFlags flags, ...) { va_list ap; char **l; diff --git a/src/basic/util.h b/src/basic/util.h index 7aca46d777..a1d1dd15c3 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -839,11 +839,13 @@ int is_dir(const char *path, bool follow); int is_device_node(const char *path); typedef enum UnquoteFlags { - UNQUOTE_RELAX = 1, - UNQUOTE_CUNESCAPE = 2, + UNQUOTE_RELAX = 1, + UNQUOTE_CUNESCAPE = 2, + UNQUOTE_CUNESCAPE_RELAX = 4, } UnquoteFlags; int unquote_first_word(const char **p, char **ret, UnquoteFlags flags); +int unquote_first_word_and_warn(const char **p, char **ret, UnquoteFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue); int unquote_many_words(const char **p, UnquoteFlags flags, ...) _sentinel_; int free_and_strdup(char **p, const char *s); diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 3e398b53e9..3cc3b33ae7 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -239,11 +239,7 @@ static int parse_argv(int argc, char *argv[]) { if (!e) return log_oom(); -#ifdef ENABLE_KDBUS a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); -#else - a = strjoin("x-machine-unix:machine=", e, NULL); -#endif if (!a) return log_oom(); diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c index aa5010c1ac..28ab1c97fc 100644 --- a/src/bus-proxyd/proxy.c +++ b/src/bus-proxyd/proxy.c @@ -275,12 +275,16 @@ int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) { return log_error_errno(r, "Couldn't determine bus scope: %m"); if (streq(scope, "system")) - strv = strv_new("/etc/dbus-1/system.conf", + strv = strv_new("/usr/share/dbus-1/system.conf", + "/etc/dbus-1/system.conf", + "/usr/share/dbus-1/system.d/", "/etc/dbus-1/system.d/", "/etc/dbus-1/system-local.conf", NULL); else if (streq(scope, "user")) - strv = strv_new("/etc/dbus-1/session.conf", + strv = strv_new("/usr/share/dbus-1/session.conf", + "/etc/dbus-1/session.conf", + "/usr/share/dbus-1/session.d/", "/etc/dbus-1/session.d/", "/etc/dbus-1/session-local.conf", NULL); diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c index 61bc08ae33..f275f6705f 100644 --- a/src/bus-proxyd/stdio-bridge.c +++ b/src/bus-proxyd/stdio-bridge.c @@ -110,11 +110,7 @@ static int parse_argv(int argc, char *argv[]) { if (!e) return log_oom(); -#ifdef ENABLE_KDBUS a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); -#else - a = strjoin("x-machine-unix:machine=", e, NULL); -#endif if (!a) return log_oom(); diff --git a/src/core/execute.c b/src/core/execute.c index 444865da86..94cc101738 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -771,7 +771,7 @@ static int setup_pam( }; pam_handle_t *handle = NULL; - sigset_t ss, old_ss; + sigset_t old_ss; int pam_code = PAM_SUCCESS; int err; char **e = NULL; @@ -868,6 +868,11 @@ static int setup_pam( /* Check if our parent process might already have * died? */ if (getppid() == parent_pid) { + sigset_t ss; + + assert_se(sigemptyset(&ss) >= 0); + assert_se(sigaddset(&ss, SIGTERM) >= 0); + for (;;) { if (sigwait(&ss, &sig) < 0) { if (errno == EINTR) @@ -1509,7 +1514,6 @@ static int exec_child( } } -#ifdef ENABLE_KDBUS if (params->bus_endpoint_fd >= 0 && context->bus_endpoint) { uid_t ep_uid = (uid == UID_INVALID) ? 0 : uid; @@ -1519,7 +1523,6 @@ static int exec_child( return r; } } -#endif /* If delegation is enabled we'll pass ownership of the cgroup * (but only in systemd's own controller hierarchy!) to the diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index f5584b6b14..e7a6bdc8c4 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -66,10 +66,8 @@ int kmod_setup(void) { /* this should never be a module */ { "unix", "/proc/net/unix", true, true, NULL }, -#ifdef ENABLE_KDBUS /* IPC is needed before we bring up any other services */ { "kdbus", "/sys/fs/kdbus", false, false, is_kdbus_wanted }, -#endif #ifdef HAVE_LIBIPTC /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */ diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 66c9145aa6..aae81c80cb 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -229,9 +229,7 @@ Service.BusName, config_parse_bus_name, 0, Service.FileDescriptorStoreMax, config_parse_unsigned, 0, offsetof(Service, n_fd_store_max) Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access) Service.Sockets, config_parse_service_sockets, 0, 0 -m4_ifdef(`ENABLE_KDBUS', -`Service.BusPolicy, config_parse_bus_endpoint_policy, 0, offsetof(Service, exec_context)', -`Service.BusPolicy, config_parse_warn_compat, DISABLED_EXPERIMENTAL, 0') +Service.BusPolicy, config_parse_bus_endpoint_policy, 0, offsetof(Service, exec_context) EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index df5fe6fb32..a48cb4029a 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -520,9 +520,9 @@ int config_parse_exec( void *data, void *userdata) { - ExecCommand **e = data, *nce; - char *path, **n; - unsigned k; + ExecCommand **e = data; + const char *p; + bool semicolon; int r; assert(filename); @@ -532,156 +532,154 @@ int config_parse_exec( e += ltype; + rvalue += strspn(rvalue, WHITESPACE); + p = rvalue; + if (isempty(rvalue)) { /* An empty assignment resets the list */ *e = exec_command_free_list(*e); return 0; } - /* We accept an absolute path as first argument, or - * alternatively an absolute prefixed with @ to allow - * overriding of argv[0]. */ - for (;;) { + do { int i; - const char *word, *state, *reason; - size_t l; + _cleanup_strv_free_ char **n = NULL; + size_t nlen = 0, nbufsize = 0; + _cleanup_free_ ExecCommand *nce = NULL; + _cleanup_free_ char *path = NULL, *firstword = NULL; + char *f; bool separate_argv0 = false, ignore = false; - path = NULL; - nce = NULL; - n = NULL; + semicolon = false; - rvalue += strspn(rvalue, WHITESPACE); + r = unquote_first_word_and_warn(&p, &firstword, UNQUOTE_CUNESCAPE, unit, filename, line, rvalue); + if (r <= 0) + return 0; - if (rvalue[0] == 0) - break; + f = firstword; + for (i = 0; i < 2; i++) { + /* We accept an absolute path as first argument, or + * alternatively an absolute prefixed with @ to allow + * overriding of argv[0]. */ + if (*f == '-' && !ignore) + ignore = true; + else if (*f == '@' && !separate_argv0) + separate_argv0 = true; + else + break; + f ++; + } - k = 0; - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - if (k == 0) { - for (i = 0; i < 2; i++) { - if (*word == '-' && !ignore) { - ignore = true; - word ++; - } - - if (*word == '@' && !separate_argv0) { - separate_argv0 = true; - word ++; - } - } - } else if (strneq(word, ";", MAX(l, 1U))) - goto found; + if (isempty(f)) { + /* First word is either "-" or "@" with no command. */ + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Empty path in command line, ignoring: \"%s\"", rvalue); + return 0; + } - k++; + if (!string_is_safe(f)) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Executable path contains special characters, ignoring: %s", rvalue); + return 0; } - if (!isempty(state)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Trailing garbage, ignoring."); + if (!path_is_absolute(f)) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Executable path is not absolute, ignoring: %s", rvalue); + return 0; + } + if (endswith(f, "/")) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Executable path specifies a directory, ignoring: %s", rvalue); return 0; } - found: - /* If separate_argv0, we'll move first element to path variable */ - n = new(char*, MAX(k + !separate_argv0, 1u)); - if (!n) - return log_oom(); + if (f == firstword) { + path = firstword; + firstword = NULL; + } else { + path = strdup(f); + if (!path) + return log_oom(); + } - k = 0; - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - char *c; - unsigned skip; - - if (separate_argv0 ? path == NULL : k == 0) { - /* first word, very special */ - skip = separate_argv0 + ignore; - - /* skip special chars in the beginning */ - if (l <= skip) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Empty path in command line, ignoring: \"%s\"", rvalue); - r = 0; - goto fail; - } + if (!separate_argv0) { + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + f = strdup(path); + if (!f) + return log_oom(); + n[nlen++] = f; + n[nlen] = NULL; + } - } else if (strneq(word, ";", MAX(l, 1U))) - /* new commandline */ - break; + path_kill_slashes(path); - else - skip = strneq(word, "\\;", MAX(l, 1U)); + for (;;) { + _cleanup_free_ char *word = NULL; - r = cunescape_length(word + skip, l - skip, UNESCAPE_RELAX, &c); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to unescape command line, ignoring: %s", rvalue); - r = 0; - goto fail; + /* Check explicitly for an unquoted semicolon as + * command separator token. */ + if (p[0] == ';' && (!p[1] || strchr(WHITESPACE, p[1]))) { + p ++; + p += strspn(p, WHITESPACE); + semicolon = true; + break; } - if (!utf8_is_valid(c)) { - log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); - r = 0; - goto fail; + /* Check for \; explicitly, to not confuse it with \\; + * or "\;" or "\\;" etc. unquote_first_word would + * return the same for all of those. */ + if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) { + p += 2; + p += strspn(p, WHITESPACE); + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + f = strdup(";"); + if (!f) + return log_oom(); + n[nlen++] = f; + n[nlen] = NULL; + continue; } - /* where to stuff this? */ - if (separate_argv0 && path == NULL) - path = c; - else - n[k++] = c; - } + r = unquote_first_word_and_warn(&p, &word, UNQUOTE_CUNESCAPE, unit, filename, line, rvalue); + if (r == 0) + break; + else if (r < 0) + return 0; - n[k] = NULL; + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + n[nlen++] = word; + n[nlen] = NULL; + word = NULL; + } - if (!n[0]) - reason = "Empty executable name or zeroeth argument"; - else if (!string_is_safe(path ?: n[0])) - reason = "Executable path contains special characters"; - else if (!path_is_absolute(path ?: n[0])) - reason = "Executable path is not absolute"; - else if (endswith(path ?: n[0], "/")) - reason = "Executable path specifies a directory"; - else - goto ok; - - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "%s, ignoring: %s", reason, rvalue); - r = 0; - goto fail; - -ok: - if (!path) { - path = strdup(n[0]); - if (!path) { - r = log_oom(); - goto fail; - } + if (!n || !n[0]) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Empty executable name or zeroeth argument, ignoring: %s", rvalue); + return 0; } nce = new0(ExecCommand, 1); - if (!nce) { - r = log_oom(); - goto fail; - } + if (!nce) + return log_oom(); nce->argv = n; nce->path = path; nce->ignore = ignore; - path_kill_slashes(nce->path); - exec_command_append_list(e, nce); - rvalue = state; - } - - return 0; + /* Do not _cleanup_free_ these. */ + n = NULL; + path = NULL; + nce = NULL; -fail: - n[k] = NULL; - strv_free(n); - free(path); - free(nce); + rvalue = p; + } while (semicolon); - return r; + return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type"); diff --git a/src/core/manager.c b/src/core/manager.c index eb80dd1b46..a1f37bbbb3 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -731,7 +731,6 @@ static int manager_setup_notify(Manager *m) { } static int manager_setup_kdbus(Manager *m) { -#ifdef ENABLE_KDBUS _cleanup_free_ char *p = NULL; assert(m); @@ -749,7 +748,6 @@ static int manager_setup_kdbus(Manager *m) { return log_debug_errno(m->kdbus_fd, "Failed to set up kdbus: %m"); log_debug("Successfully set up kdbus on %s", p); -#endif return 0; } diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index c35248eeae..42a6b952b9 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -104,10 +104,8 @@ static const MountPoint mount_table[] = { { "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, is_efi_boot, MNT_NONE }, #endif -#ifdef ENABLE_KDBUS { "kdbusfs", "/sys/fs/kdbus", "kdbusfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_IN_CONTAINER }, -#endif }; /* These are API file systems that might be mounted by other software, diff --git a/src/core/service.c b/src/core/service.c index 71252e29e2..fa1e80b710 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -568,14 +568,12 @@ static int service_add_extras(Service *s) { s->notify_access = NOTIFY_MAIN; if (s->bus_name) { -#ifdef ENABLE_KDBUS const char *n; n = strjoina(s->bus_name, ".busname"); r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, n, NULL, true); if (r < 0) return r; -#endif r = unit_watch_bus_name(UNIT(s), s->bus_name); if (r < 0) @@ -1180,7 +1178,6 @@ static int service_spawn( } else path = UNIT(s)->cgroup_path; -#ifdef ENABLE_KDBUS if (s->exec_context.bus_endpoint) { r = bus_kernel_create_endpoint(UNIT(s)->manager->running_as == MANAGER_SYSTEM ? "system" : "user", UNIT(s)->id, &bus_endpoint_path); @@ -1192,7 +1189,6 @@ static int service_spawn( * as the service is running. */ exec_params.bus_endpoint_fd = s->bus_endpoint_fd = r; } -#endif exec_params.argv = argv; exec_params.fds = fds; diff --git a/src/import/pull.c b/src/import/pull.c index ca33d2f3fa..ca7be6be85 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -245,15 +245,15 @@ static int pull_dkr(int argc, char *argv[], void *userdata) { if (digest) { reference = digest + 1; name = strndupa(argv[1], digest - argv[1]); - } - - reference = strchr(argv[1], ':'); - if (reference) { - name = strndupa(argv[1], reference - argv[1]); - reference++; } else { - name = argv[1]; - reference = "latest"; + reference = strchr(argv[1], ':'); + if (reference) { + name = strndupa(argv[1], reference - argv[1]); + reference++; + } else { + name = argv[1]; + reference = "latest"; + } } if (!dkr_name_is_valid(name)) { diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index c2fc123e42..adefa1b026 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -62,10 +62,19 @@ static void test_close(JournalFile *f) { static void append_number(JournalFile *f, int n, uint64_t *seqnum) { char *p; dual_timestamp ts; + static dual_timestamp previous_ts = {}; struct iovec iovec[1]; dual_timestamp_get(&ts); + if (ts.monotonic <= previous_ts.monotonic) + ts.monotonic = previous_ts.monotonic + 1; + + if (ts.realtime <= previous_ts.realtime) + ts.realtime = previous_ts.realtime + 1; + + previous_ts = ts; + assert_se(asprintf(&p, "NUMBER=%d", n) >= 0); iovec[0].iov_base = p; iovec[0].iov_len = strlen(p); diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c index e1146c692d..b5ecf2f375 100644 --- a/src/journal/test-journal-stream.c +++ b/src/journal/test-journal-stream.c @@ -80,6 +80,7 @@ int main(int argc, char *argv[]) { char *z; const void *data; size_t l; + dual_timestamp previous_ts = DUAL_TIMESTAMP_NULL; /* journal_file_open requires a valid machine id */ if (access("/etc/machine-id", F_OK) != 0) @@ -101,6 +102,14 @@ int main(int argc, char *argv[]) { dual_timestamp_get(&ts); + if (ts.monotonic <= previous_ts.monotonic) + ts.monotonic = previous_ts.monotonic + 1; + + if (ts.realtime <= previous_ts.realtime) + ts.realtime = previous_ts.realtime + 1; + + previous_ts = ts; + assert_se(asprintf(&p, "NUMBER=%u", i) >= 0); iovec[0].iov_base = p; iovec[0].iov_len = strlen(p); diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 6853038b67..6a0d270739 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -928,6 +928,8 @@ static int client_initialize_time_events(sd_dhcp_client *client) { r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); + if (r < 0) + goto error; r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); if (r < 0) diff --git a/src/libsystemd/.gitignore b/src/libsystemd/.gitignore index d48e1cdd13..50a1692374 100644 --- a/src/libsystemd/.gitignore +++ b/src/libsystemd/.gitignore @@ -1,2 +1 @@ -/libsystemd.sym /libsystemd.pc diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym index 3121e71282..809db1f6cc 100644 --- a/src/libsystemd/libsystemd.sym.m4 +++ b/src/libsystemd/libsystemd.sym @@ -459,41 +459,3 @@ global: sd_event_source_get_signal; sd_event_source_get_child_pid; } LIBSYSTEMD_220; - -m4_ifdef(`ENABLE_KDBUS', -LIBSYSTEMD_FUTURE { -global: - /* sd-utf8 */ - sd_utf8_is_valid; - sd_ascii_is_valid; - - /* sd-resolve */ - sd_resolve_default; - sd_resolve_new; - sd_resolve_ref; - sd_resolve_unref; - sd_resolve_get_fd; - sd_resolve_get_events; - sd_resolve_get_timeout; - sd_resolve_process; - sd_resolve_wait; - sd_resolve_get_tid; - sd_resolve_attach_event; - sd_resolve_detach_event; - sd_resolve_get_event; - sd_resolve_getaddrinfo; - sd_resolve_getnameinfo; - sd_resolve_res_query; - sd_resolve_res_search; - sd_resolve_query_ref; - sd_resolve_query_unref; - sd_resolve_query_is_done; - sd_resolve_query_get_userdata; - sd_resolve_query_set_userdata; - sd_resolve_query_get_resolve; - - /* sd-path */ - sd_path_home; - sd_path_search; -} LIBSYSTEMD_220; -) diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 88c058889a..c3e20ee1bf 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -141,6 +141,7 @@ struct sd_bus_slot { void *userdata; BusSlotType type:5; bool floating:1; + bool match_added:1; char *description; LIST_FIELDS(sd_bus_slot, slots); diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 3aaaabf4ed..f08db2da89 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -29,8 +29,8 @@ #include <sys/prctl.h> /* When we include libgen.h because we need dirname() we immediately - * undefine basename() since libgen.h defines it as a macro to the XDG - * version which is really broken. */ + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ #include <libgen.h> #undef basename diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index 7c5264fad4..132b37526e 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -1149,3 +1149,40 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) { for (c = node->child; c; c = c->next) bus_match_dump(c, level + 1); } + +enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components) { + bool found_driver = false; + unsigned i; + + if (n_components <= 0) + return BUS_MATCH_GENERIC; + + assert(components); + + /* Checks whether the specified match can only match the + * pseudo-service for local messages, which we detect by + * sender, interface or path. If a match is not restricted to + * local messages, then we check if it only matches on the + * driver. */ + + for (i = 0; i < n_components; i++) { + const struct bus_match_component *c = components + i; + + if (c->type == BUS_MATCH_SENDER) { + if (streq_ptr(c->value_str, "org.freedesktop.DBus.Local")) + return BUS_MATCH_LOCAL; + + if (streq_ptr(c->value_str, "org.freedesktop.DBus")) + found_driver = true; + } + + if (c->type == BUS_MATCH_INTERFACE && streq_ptr(c->value_str, "org.freedesktop.DBus.Local")) + return BUS_MATCH_LOCAL; + + if (c->type == BUS_MATCH_PATH && streq_ptr(c->value_str, "/org/freedesktop/DBus/Local")) + return BUS_MATCH_LOCAL; + } + + return found_driver ? BUS_MATCH_DRIVER : BUS_MATCH_GENERIC; + +} diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h index af5f65d073..56516be9fa 100644 --- a/src/libsystemd/sd-bus/bus-match.h +++ b/src/libsystemd/sd-bus/bus-match.h @@ -73,6 +73,12 @@ struct bus_match_component { char *value_str; }; +enum bus_match_scope { + BUS_MATCH_GENERIC, + BUS_MATCH_LOCAL, + BUS_MATCH_DRIVER, +}; + int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m); int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback); @@ -90,3 +96,5 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components); void bus_match_parse_free(struct bus_match_component *components, unsigned n_components); char *bus_match_to_string(struct bus_match_component *components, unsigned n_components); + +enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components); diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 8060e9882c..c452477566 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -89,7 +89,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) { case BUS_MATCH_CALLBACK: - if (slot->bus->bus_client) + if (slot->match_added) bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie); slot->bus->match_callbacks_modified = true; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 2805b29839..5dd6468707 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1239,18 +1239,9 @@ int bus_set_address_user(sd_bus *b) { if (!ee) return -ENOMEM; -#ifdef ENABLE_KDBUS (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, getuid(), ee); -#else - (void) asprintf(&b->address, UNIX_USER_BUS_ADDRESS_FMT, ee); -#endif - } else { -#ifdef ENABLE_KDBUS + } else (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()); -#else - return -ECONNREFUSED; -#endif - } if (!b->address) return -ENOMEM; @@ -1372,11 +1363,7 @@ int bus_set_address_system_machine(sd_bus *b, const char *machine) { if (!e) return -ENOMEM; -#ifdef ENABLE_KDBUS b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); -#else - b->address = strjoin("x-machine-unix:machine=", e, NULL); -#endif if (!b->address) return -ENOMEM; @@ -2952,22 +2939,33 @@ _public_ int sd_bus_add_match( s->match_callback.cookie = ++bus->match_cookie; if (bus->bus_client) { + enum bus_match_scope scope; - if (!bus->is_kernel) { - /* When this is not a kernel transport, we - * store the original match string, so that we - * can use it to remove the match again */ + scope = bus_match_get_scope(components, n_components); - s->match_callback.match_string = strdup(match); - if (!s->match_callback.match_string) { - r = -ENOMEM; - goto finish; + /* Do not install server-side matches for matches + * against the local service, interface or bus + * path. */ + if (scope != BUS_MATCH_LOCAL) { + + if (!bus->is_kernel) { + /* When this is not a kernel transport, we + * store the original match string, so that we + * can use it to remove the match again */ + + s->match_callback.match_string = strdup(match); + if (!s->match_callback.match_string) { + r = -ENOMEM; + goto finish; + } } - } - r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie); - if (r < 0) - goto finish; + r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie); + if (r < 0) + goto finish; + + s->match_added = true; + } } bus->match_callbacks_modified = true; diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c index 40c67046da..a1687b1c7b 100644 --- a/src/libsystemd/sd-bus/test-bus-match.c +++ b/src/libsystemd/sd-bus/test-bus-match.c @@ -77,6 +77,15 @@ static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char return r; } +static void test_match_scope(const char *match, enum bus_match_scope scope) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; + + assert_se(bus_match_parse(match, &components, &n_components) >= 0); + assert_se(bus_match_get_scope(components, n_components) == scope); + bus_match_parse_free(components, n_components); +} + int main(int argc, char *argv[]) { struct bus_match_node root = { .type = BUS_MATCH_ROOT, @@ -142,5 +151,12 @@ int main(int argc, char *argv[]) { bus_match_free(&root); + test_match_scope("interface='foobar'", BUS_MATCH_GENERIC); + test_match_scope("", BUS_MATCH_GENERIC); + test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); + test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); + test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL); + test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER); + return 0; } diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 00880c983b..76964aa0cc 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -468,24 +468,22 @@ static bool event_pid_changed(sd_event *e) { return e->original_pid != getpid(); } -static int source_io_unregister(sd_event_source *s) { +static void source_io_unregister(sd_event_source *s) { int r; assert(s); assert(s->type == SOURCE_IO); if (event_pid_changed(s->event)) - return 0; + return; if (!s->io.registered) - return 0; + return; r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL); - if (r < 0) - return -errno; + assert_log(r >= 0); s->io.registered = false; - return 0; } static int source_io_register( @@ -1457,10 +1455,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { switch (s->type) { case SOURCE_IO: - r = source_io_unregister(s); - if (r < 0) - return r; - + source_io_unregister(s); s->enabled = m; break; diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c index c27b01db96..9a8d682107 100644 --- a/src/libudev/libudev-device.c +++ b/src/libudev/libudev-device.c @@ -871,7 +871,7 @@ _public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_ udev_list_cleanup(&udev_device->sysattrs); FOREACH_DEVICE_SYSATTR(udev_device->device, sysattr) - udev_list_entry_add(&udev_device->properties, sysattr, NULL); + udev_list_entry_add(&udev_device->sysattrs, sysattr, NULL); udev_device->sysattrs_read = true; } diff --git a/src/login/logind-button.c b/src/login/logind-button.c index 8079d0b5aa..210b889c4f 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -100,7 +100,7 @@ static void button_lid_switch_handle_action(Manager *manager, bool is_edge) { assert(manager); /* If we are docked, handle the lid switch differently */ - if (manager_is_docked_or_multiple_displays(manager)) + if (manager_is_docked_or_external_displays(manager)) handle_action = manager->handle_lid_switch_docked; else handle_action = manager->handle_lid_switch; diff --git a/src/login/logind-core.c b/src/login/logind-core.c index f9e6ddfb3f..a6c01f7d85 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -477,7 +477,7 @@ int manager_spawn_autovt(Manager *m, unsigned int vtnr) { return r; } -bool manager_is_docked(Manager *m) { +static bool manager_is_docked(Manager *m) { Iterator i; Button *b; @@ -488,7 +488,7 @@ bool manager_is_docked(Manager *m) { return false; } -int manager_count_displays(Manager *m) { +static int manager_count_external_displays(Manager *m) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; @@ -510,7 +510,8 @@ int manager_count_displays(Manager *m) { udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; struct udev_device *p; - const char *status; + const char *status, *enabled, *dash, *nn, *i; + bool external = false; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); if (!d) @@ -526,6 +527,40 @@ int manager_count_displays(Manager *m) { if (!streq_ptr(udev_device_get_subsystem(p), "drm")) continue; + nn = udev_device_get_sysname(d); + if (!nn) + continue; + + /* Ignore internal displays: the type is encoded in + * the sysfs name, as the second dash seperated item + * (the first is the card name, the last the connector + * number). We implement a whitelist of external + * displays here, rather than a whitelist, to ensure + * we don't block suspends too eagerly. */ + dash = strchr(nn, '-'); + if (!dash) + continue; + + dash++; + FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-" + "Composite-", "SVIDEO-", "Component-", + "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") { + + if (startswith(dash, i)) { + external = true; + break; + } + } + if (!external) + continue; + + /* Ignore ports that are not enabled */ + enabled = udev_device_get_sysattr_value(d, "enabled"); + if (!enabled) + continue; + if (!streq_ptr(enabled, "enabled")) + continue; + /* We count any connector which is not explicitly * "disconnected" as connected. */ status = udev_device_get_sysattr_value(d, "status"); @@ -536,7 +571,7 @@ int manager_count_displays(Manager *m) { return n; } -bool manager_is_docked_or_multiple_displays(Manager *m) { +bool manager_is_docked_or_external_displays(Manager *m) { int n; /* If we are docked don't react to lid closing */ @@ -547,11 +582,11 @@ bool manager_is_docked_or_multiple_displays(Manager *m) { /* If we have more than one display connected, * assume that we are docked. */ - n = manager_count_displays(m); + n = manager_count_external_displays(m); if (n < 0) log_warning_errno(n, "Display counting failed: %m"); - else if (n > 1) { - log_debug("Multiple (%i) displays connected.", n); + else if (n >= 1) { + log_debug("External (%i) displays connected.", n); return true; } diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index e6f9ec7845..8ebcd3f5ca 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -258,7 +258,7 @@ static int property_get_docked( assert(reply); assert(m); - return sd_bus_message_append(reply, "b", manager_is_docked_or_multiple_displays(m)); + return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m)); } static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 6720899def..21d7268120 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -36,9 +36,10 @@ #include "bus-error.h" #include "conf-parser.h" #include "clean-ipc.h" -#include "logind-user.h" #include "smack-util.h" #include "formats-util.h" +#include "label.h" +#include "logind-user.h" User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { User *u; @@ -105,7 +106,7 @@ void user_free(User *u) { free(u); } -int user_save(User *u) { +static int user_save_internal(User *u) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; @@ -113,9 +114,6 @@ int user_save(User *u) { assert(u); assert(u->state_file); - if (!u->started) - return 0; - r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0); if (r < 0) goto finish; @@ -258,6 +256,15 @@ finish: return r; } +int user_save(User *u) { + assert(u); + + if (!u->started) + return 0; + + return user_save_internal (u); +} + int user_load(User *u) { _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL; Session *s = NULL; @@ -323,7 +330,7 @@ static int user_mkdir_runtime_path(User *u) { if (path_is_mount_point(p, 0) <= 0) { _cleanup_free_ char *t = NULL; - (void) mkdir(p, 0700); + (void) mkdir_label(p, 0700); if (mac_smack_use()) r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size); @@ -351,6 +358,10 @@ static int user_mkdir_runtime_path(User *u) { goto fail; } } + + r = label_fix(p, false, false); + if (r < 0) + log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p); } u->runtime_path = p; @@ -453,6 +464,12 @@ int user_start(User *u) { if (r < 0) return r; + /* Save the user data so far, because pam_systemd will read the + * XDG_RUNTIME_DIR out of it while starting up systemd --user. + * We need to do user_save_internal() because we have not + * "officially" started yet. */ + user_save_internal(u); + /* Spawn user systemd */ r = user_start_service(u); if (r < 0) @@ -704,7 +721,7 @@ UserState user_get_state(User *u) { if (u->stopping) return USER_CLOSING; - if (u->slice_job || u->service_job) + if (!u->started || u->slice_job || u->service_job) return USER_OPENING; if (u->sessions) { diff --git a/src/login/logind.h b/src/login/logind.h index cd226f55fc..feb381d0b1 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -156,9 +156,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t); int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); -bool manager_is_docked(Manager *m); -int manager_count_displays(Manager *m); -bool manager_is_docked_or_multiple_displays(Manager *m); +bool manager_is_docked_or_external_displays(Manager *m); extern const sd_bus_vtable manager_vtable[]; diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index b5d419000c..0ebdfdf19e 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -177,7 +177,6 @@ static int export_legacy_dbus_address( uid_t uid, const char *runtime) { -#ifdef ENABLE_KDBUS _cleanup_free_ char *s = NULL; int r; @@ -195,7 +194,7 @@ static int export_legacy_dbus_address( pam_syslog(handle, LOG_ERR, "Failed to set bus variable."); return r; } -#endif + return PAM_SUCCESS; } diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 0892479a9a..7813a0bcc7 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -24,8 +24,8 @@ #include <sys/mount.h> /* When we include libgen.h because we need dirname() we immediately - * undefine basename() since libgen.h defines it as a macro to the XDG - * version which is really broken. */ + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ #include <libgen.h> #undef basename @@ -509,11 +509,7 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu if (r < 0) return r; -#ifdef ENABLE_KDBUS # define ADDRESS_FMT "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI -#else -# define ADDRESS_FMT "x-machine-unix:pid=%1$" PID_PRI -#endif if (asprintf(&address, ADDRESS_FMT, m->leader) < 0) return log_oom(); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 3c31629d1e..d1154de08a 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -4972,6 +4972,10 @@ finish: if (pid > 0) kill(pid, SIGKILL); + /* Try to flush whatever is still queued in the pty */ + if (master >= 0) + (void) copy_bytes(master, STDOUT_FILENO, (off_t) -1, false); + loop_remove(loop_nr, &image_fd); if (remove_subvol && arg_directory) { diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index 466f9aa601..bd8c988751 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -223,7 +223,7 @@ int acl_search_groups(const char *path, char ***ret_groups) { return ret; } -int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) { +int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) { _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */ _cleanup_strv_free_ char **split; char **entry; @@ -232,7 +232,7 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) split = strv_split(text, ","); if (!split) - return log_oom(); + return -ENOMEM; STRV_FOREACH(entry, split) { char *p; @@ -245,9 +245,9 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) r = strv_push(&d, p); else r = strv_push(&a, *entry); + if (r < 0) + return r; } - if (r < 0) - return r; if (!strv_isempty(a)) { _cleanup_free_ char *join; @@ -258,7 +258,7 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) a_acl = acl_from_text(join); if (!a_acl) - return -EINVAL; + return -errno; if (want_mask) { r = calc_acl_mask_if_needed(&a_acl); @@ -276,7 +276,7 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) d_acl = acl_from_text(join); if (!d_acl) - return -EINVAL; + return -errno; if (want_mask) { r = calc_acl_mask_if_needed(&d_acl); @@ -288,6 +288,7 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) *acl_access = a_acl; *acl_default = d_acl; a_acl = d_acl = NULL; + return 0; } diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h index c8bcc266d0..cf612e8722 100644 --- a/src/shared/acl-util.h +++ b/src/shared/acl-util.h @@ -33,7 +33,7 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry); int calc_acl_mask_if_needed(acl_t *acl_p); int add_base_acls_if_needed(acl_t *acl_p, const char *path); int acl_search_groups(const char* path, char ***ret_groups); -int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask); +int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask); int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl); /* acl_free takes multiple argument types. diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 8fcc289957..11350dad71 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -545,7 +545,6 @@ int bus_open_system_systemd(sd_bus **_bus) { * directly to the system instance, instead of going via the * bus */ -#ifdef ENABLE_KDBUS r = sd_bus_new(&bus); if (r < 0) return r; @@ -564,7 +563,6 @@ int bus_open_system_systemd(sd_bus **_bus) { } bus = sd_bus_unref(bus); -#endif r = sd_bus_new(&bus); if (r < 0) @@ -598,7 +596,6 @@ int bus_open_user_systemd(sd_bus **_bus) { assert(_bus); -#ifdef ENABLE_KDBUS r = sd_bus_new(&bus); if (r < 0) return r; @@ -616,7 +613,6 @@ int bus_open_user_systemd(sd_bus **_bus) { } bus = sd_bus_unref(bus); -#endif e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) @@ -2034,15 +2030,22 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send bool is_kdbus_wanted(void) { _cleanup_free_ char *value = NULL; +#ifdef ENABLE_KDBUS + const bool configured = true; +#else + const bool configured = false; +#endif + int r; - if (get_proc_cmdline_key("kdbus", NULL) <= 0) { - r = get_proc_cmdline_key("kdbus=", &value); - if (r <= 0 || parse_boolean(value) != 1) - return false; - } + if (get_proc_cmdline_key("kdbus", NULL) > 0) + return true; + + r = get_proc_cmdline_key("kdbus=", &value); + if (r <= 0) + return configured; - return true; + return parse_boolean(value) == 1; } bool is_kdbus_available(void) { diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index ac5eb16f62..068da465d9 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -274,8 +274,10 @@ static int output_short( if (r < 0) return log_error_errno(r, "Failed to get journal fields: %m"); - if (!message) + if (!message) { + log_debug("Skipping message without MESSAGE= field."); return 0; + } if (!(flags & OUTPUT_SHOW_ALL)) strip_tab_ansi(&message, &message_len); diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c index 2fe4eb81cf..9d39beb340 100644 --- a/src/shared/watchdog.c +++ b/src/shared/watchdog.c @@ -60,8 +60,13 @@ static int update_timeout(void) { flags = WDIOS_ENABLECARD; r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); - if (r < 0) - return log_warning_errno(errno, "Failed to enable hardware watchdog: %m"); + if (r < 0) { + /* ENOTTY means the watchdog is always enabled so we're fine */ + log_full(errno == ENOTTY ? LOG_DEBUG : LOG_WARNING, + "Failed to enable hardware watchdog: %m"); + if (errno != ENOTTY) + return -errno; + } r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0); if (r < 0) diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c index 2d109a30e7..f37cb49c85 100644 --- a/src/test/test-barrier.c +++ b/src/test/test-barrier.c @@ -438,6 +438,16 @@ TEST_BARRIER(test_barrier_pending_exit, TEST_BARRIER_WAIT_SUCCESS(pid2)); int main(int argc, char *argv[]) { + /* + * This test uses real-time alarms and sleeps to test for CPU races + * explicitly. This is highly fragile if your system is under load. We + * already increased the BASE_TIME value to make the tests more robust, + * but that just makes the test take significantly longer. Hence, + * disable the test by default, so it will not break CI. + */ + if (argc < 2) + return EXIT_TEST_SKIP; + log_parse_environment(); log_open(); diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c index 289dddbaac..72f874d8a9 100644 --- a/src/test/test-cgroup-mask.c +++ b/src/test/test-cgroup-mask.c @@ -77,12 +77,12 @@ static int test_cgroup_mask(void) { assert_se(unit_get_members_mask(root) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY)); /* Verify aggregation of sibling masks. */ - assert_se(unit_get_siblings_mask(son) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported)); - assert_se(unit_get_siblings_mask(daughter) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported)); + assert_se(unit_get_siblings_mask(son) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY)); + assert_se(unit_get_siblings_mask(daughter) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY)); assert_se(unit_get_siblings_mask(grandchild) == 0); - assert_se(unit_get_siblings_mask(parent_deep) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported)); - assert_se(unit_get_siblings_mask(parent) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY) & m->cgroup_supported)); - assert_se(unit_get_siblings_mask(root) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY) & m->cgroup_supported)); + assert_se(unit_get_siblings_mask(parent_deep) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY)); + assert_se(unit_get_siblings_mask(parent) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY)); + assert_se(unit_get_siblings_mask(root) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY)); /* Verify aggregation of target masks. */ assert_se(unit_get_target_mask(son) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported)); diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c index 767cbd90e9..d0e65001f5 100644 --- a/src/test/test-hashmap.c +++ b/src/test/test-hashmap.c @@ -24,38 +24,17 @@ void test_hashmap_funcs(void); void test_ordered_hashmap_funcs(void); static void test_ordered_hashmap_next(void) { - OrderedHashmap *m; - char *val1, *val2, *val3, *val4, *r; - - m = ordered_hashmap_new(&string_hash_ops); - val1 = strdup("val1"); - assert_se(val1); - val2 = strdup("val2"); - assert_se(val2); - val3 = strdup("val3"); - assert_se(val3); - val4 = strdup("val4"); - assert_se(val4); - - ordered_hashmap_put(m, "key 1", val1); - ordered_hashmap_put(m, "key 2", val2); - ordered_hashmap_put(m, "key 3", val3); - ordered_hashmap_put(m, "key 4", val4); - - r = ordered_hashmap_next(m, "key 1"); - assert_se(streq(r, val2)); - r = ordered_hashmap_next(m, "key 2"); - assert_se(streq(r, val3)); - r = ordered_hashmap_next(m, "key 3"); - assert_se(streq(r, val4)); - r = ordered_hashmap_next(m, "key 4"); - assert_se(!r); - r = ordered_hashmap_next(NULL, "key 1"); - assert_se(!r); - r = ordered_hashmap_next(m, "key 5"); - assert_se(!r); - - ordered_hashmap_free_free(m); + _cleanup_ordered_hashmap_free_ OrderedHashmap *m = NULL; + int i; + + assert_se(m = ordered_hashmap_new(NULL)); + for (i = -2; i <= 2; i++) + assert_se(ordered_hashmap_put(m, INT_TO_PTR(i), INT_TO_PTR(i+10)) == 1); + for (i = -2; i <= 1; i++) + assert_se(ordered_hashmap_next(m, INT_TO_PTR(i)) == INT_TO_PTR(i+11)); + assert_se(!ordered_hashmap_next(m, INT_TO_PTR(2))); + assert_se(!ordered_hashmap_next(NULL, INT_TO_PTR(1))); + assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3))); } static void test_uint64_compare_func(void) { diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index a8025c825b..8358789e6f 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -145,19 +145,19 @@ static void test_config_parse_exec(void) { assert_se(r == 0); assert_se(c1->command_next == NULL); - log_info("/* no command, check for bad memory access */"); + log_info("/* no command, whitespace only, reset */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, " ", &c, NULL); assert_se(r == 0); - assert_se(c1->command_next == NULL); + assert_se(c == NULL); log_info("/* ignore && honour_argv0 */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-@/RValue///slashes3 argv0a r1", &c, NULL); assert_se(r >= 0); - c1 = c1->command_next; + c1 = c; check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true); log_info("/* ignore && honour_argv0 */"); @@ -195,6 +195,19 @@ static void test_config_parse_exec(void) { c1 = c1->command_next; check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false); + log_info("/* two semicolons in a row */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ; ; " + "/goo/goo boo", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); + + /* second command fails because the executable name is ";" */ + assert_se(c1->command_next == NULL); + log_info("/* trailing semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, @@ -206,6 +219,26 @@ static void test_config_parse_exec(void) { assert_se(c1->command_next == NULL); + log_info("/* trailing semicolon, no whitespace */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ;", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); + + assert_se(c1->command_next == NULL); + + log_info("/* trailing semicolon in single quotes */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ';'", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", ";", true); + log_info("/* escaped semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, @@ -218,12 +251,22 @@ static void test_config_parse_exec(void) { log_info("/* escaped semicolon with following arg */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, - "/sbin/find \\; x", + "/sbin/find \\; /x", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/sbin/find", NULL, ";", "/x", false); + + log_info("/* escaped semicolon as part of an expression */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/sbin/find \\;x", &c, NULL); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, - "/sbin/find", NULL, ";", "x", false); + "/sbin/find", NULL, "\\;x", NULL, false); log_info("/* encoded semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, @@ -234,6 +277,25 @@ static void test_config_parse_exec(void) { c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); + log_info("/* quoted semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/find \";\"", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); + + log_info("/* quoted semicolon with following arg */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/sbin/find \";\" /x", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/sbin/find", NULL, ";", "/x", false); + log_info("/* spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, diff --git a/src/test/test-util.c b/src/test/test-util.c index ed8db45115..ad9ea3bcce 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -1304,6 +1304,244 @@ static void test_unquote_first_word(void) { assert_se(streq(t, "pi\360\237\222\251le")); free(t); assert_se(p == original + 32); + + p = original = "fooo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word(&p, &t, 0) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0); + assert_se(streq(t, "foo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0); + assert_se(streq(t, "foo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) == -EINVAL); + assert_se(p == original + 5); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\ bar")); + free(t); + assert_se(p == original + 10); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "\\w+@\\K[\\d.]+")); + free(t); + assert_se(p == original + 12); + + p = original = "\\w+\\b"; + assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "\\w+\b")); + free(t); + assert_se(p == original + 5); +} + +static void test_unquote_first_word_and_warn(void) { + const char *p, *original; + char *t; + + p = original = "foobar waldo"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 7); + + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(p == original + 12); + + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == 0); + assert_se(!t); + assert_se(p == original + 12); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 9); + + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(p == original + 16); + + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == 0); + assert_se(!t); + assert_se(p == original + 16); + + p = original = "\""; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'fooo"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\'fooo"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(p == original + 5); + + p = original = " foo\\ba\\x6ar "; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo\ba\x6ar")); + free(t); + assert_se(p == original + 13); + + p = original = " foo\\ba\\x6ar "; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobax6ar")); + free(t); + assert_se(p == original + 13); + + p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "föo")); + free(t); + assert_se(p == original + 13); + + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "pi\360\237\222\251le")); + free(t); + assert_se(p == original + 32); + + p = original = "fooo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(p == original + 5); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\ bar")); + free(t); + assert_se(p == original + 10); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "\\w+@\\K[\\d.]+")); + free(t); + assert_se(p == original + 12); + + p = original = "\\w+\\b"; + assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "\\w+\b")); + free(t); + assert_se(p == original + 5); } static void test_unquote_many_words(void) { @@ -1610,6 +1848,7 @@ int main(int argc, char *argv[]) { test_glob_exists(); test_execute_directory(); test_unquote_first_word(); + test_unquote_first_word_and_warn(); test_unquote_many_words(); test_parse_proc_cmdline(); test_raw_clone(); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 027a5c2ca8..42f757c4b7 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -496,9 +496,10 @@ static int dir_cleanup( } if (mountpoint && S_ISREG(s.st_mode)) - if ((streq(dent->d_name, ".journal") && s.st_uid == 0) || - streq(dent->d_name, "aquota.user") || - streq(dent->d_name, "aquota.group")) { + if (s.st_uid == 0 && STR_IN_SET(dent->d_name, + ".journal", + "aquota.user", + "aquota.group")) { log_debug("Skipping \"%s\".", sub_path); continue; } diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 5ce11606c9..c205f1d5ec 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -43,6 +43,7 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "terminal-util.h" #include "signal-util.h" #include "event-util.h" #include "netlink-util.h" @@ -435,7 +436,6 @@ static void worker_spawn(Manager *manager, struct event *event) { if (fd_lock >= 0 && flock(fd_lock, LOCK_SH|LOCK_NB) < 0) { log_debug_errno(errno, "Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d)); fd_lock = safe_close(fd_lock); - r = -EAGAIN; goto skip; } } @@ -1687,6 +1687,10 @@ int main(int argc, char *argv[]) { log_info("starting version " VERSION); + /* connect /dev/null to stdin, stdout, stderr */ + if (log_get_max_level() < LOG_DEBUG) + (void) make_null_stdio(); + pid = fork(); switch (pid) { case 0: |