summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/env-util.h1
-rw-r--r--src/basic/path-util.h6
-rw-r--r--src/core/execute.c14
-rw-r--r--src/nss-mymachines/nss-mymachines.c44
-rw-r--r--src/nss-resolve/nss-resolve.c29
-rw-r--r--src/partition/growfs.c4
-rw-r--r--src/shared/bus-unit-util.c4
7 files changed, 94 insertions, 8 deletions
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index ef9398e618..174433ea91 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -6,6 +6,7 @@
#include <stdio.h>
#include "macro.h"
+#include "string.h"
bool env_name_is_valid(const char *e);
bool env_value_is_valid(const char *e);
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 8277c6b916..49604eab80 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -58,10 +58,10 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
/* Note: the search terminates on the first NULL item. */
#define PATH_IN_SET(p, ...) \
({ \
- char **s; \
+ char **_s; \
bool _found = false; \
- STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \
- if (path_equal(p, *s)) { \
+ STRV_FOREACH(_s, STRV_MAKE(__VA_ARGS__)) \
+ if (path_equal(p, *_s)) { \
_found = true; \
break; \
} \
diff --git a/src/core/execute.c b/src/core/execute.c
index 0f36f6c825..ed3e1459df 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2838,10 +2838,22 @@ static int exec_child(
}
}
+ /* We are about to invoke NSS and PAM modules. Let's tell them what we are doing here, maybe they care. This is
+ * used by nss-resolve to disable itself when we are about to start systemd-resolved, to avoid deadlocks. Note
+ * that these env vars do not survive the execve(), which means they really only apply to the PAM and NSS
+ * invocations themselves. Also note that while we'll only invoke NSS modules involved in user management they
+ * might internally call into other NSS modules that are involved in hostname resolution, we never know. */
+ if (setenv("SYSTEMD_ACTIVATION_UNIT", unit->id, true) != 0 ||
+ setenv("SYSTEMD_ACTIVATION_SCOPE", MANAGER_IS_SYSTEM(unit->manager) ? "system" : "user", true) != 0) {
+ *exit_status = EXIT_MEMORY;
+ return log_unit_error_errno(unit, errno, "Failed to update environment: %m");
+ }
+
if (context->dynamic_user && dcreds) {
_cleanup_strv_free_ char **suggested_paths = NULL;
- /* Make sure we bypass our own NSS module for any NSS checks */
+ /* On top of that, make sure we bypass our own NSS module nss-systemd comprehensively for any NSS
+ * checks, if DynamicUser=1 is used, as we shouldn't create a feedback loop with ourselves here.*/
if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) {
*exit_status = EXIT_USER;
return log_unit_error_errno(unit, errno, "Failed to update environment: %m");
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index 9b81cd9ad1..3d1fc28353 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -63,6 +63,20 @@ static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
return 0;
}
+static bool avoid_deadlock(void) {
+
+ /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager
+ * code activating systemd-machined.service. After all, we shouldn't synchronously do lookups to
+ * systemd-machined if we are required to finish before it can be started. This of course won't detect all
+ * possible dead locks of this kind, but it should work for the most obvious cases. */
+
+ if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */
+ return false;
+
+ return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-machined.service") &&
+ streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system");
+}
+
enum nss_status _nss_mymachines_gethostbyname4_r(
const char *name,
struct gaih_addrtuple **pat,
@@ -103,6 +117,11 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
goto fail;
}
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -255,6 +274,11 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
goto fail;
}
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -425,6 +449,11 @@ enum nss_status _nss_mymachines_getpwnam_r(
* running on the host. */
return NSS_STATUS_NOTFOUND;
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -502,6 +531,11 @@ enum nss_status _nss_mymachines_getpwuid_r(
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
return NSS_STATUS_NOTFOUND;
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -594,6 +628,11 @@ enum nss_status _nss_mymachines_getgrnam_r(
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
return NSS_STATUS_NOTFOUND;
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -668,6 +707,11 @@ enum nss_status _nss_mymachines_getgrgid_r(
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
return NSS_STATUS_NOTFOUND;
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
index b2bb698ded..a28b5d8ba8 100644
--- a/src/nss-resolve/nss-resolve.c
+++ b/src/nss-resolve/nss-resolve.c
@@ -91,6 +91,20 @@ static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) {
return IN6_IS_ADDR_LINKLOCAL(&in6) ? ifindex : 0;
}
+static bool avoid_deadlock(void) {
+
+ /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager
+ * code activating systemd-resolved.service. After all, we shouldn't synchronously do lookups to
+ * systemd-resolved if we are required to finish before it can be started. This of course won't detect all
+ * possible dead locks of this kind, but it should work for the most obvious cases. */
+
+ if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */
+ return false;
+
+ return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-resolved.service") &&
+ streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system");
+}
+
enum nss_status _nss_resolve_gethostbyname4_r(
const char *name,
struct gaih_addrtuple **pat,
@@ -117,6 +131,11 @@ enum nss_status _nss_resolve_gethostbyname4_r(
assert(errnop);
assert(h_errnop);
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -292,6 +311,11 @@ enum nss_status _nss_resolve_gethostbyname3_r(
goto fail;
}
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
@@ -479,6 +503,11 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
return NSS_STATUS_UNAVAIL;
}
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
diff --git a/src/partition/growfs.c b/src/partition/growfs.c
index d2053cd391..6f1aa28933 100644
--- a/src/partition/growfs.c
+++ b/src/partition/growfs.c
@@ -24,8 +24,8 @@
#include "path-util.h"
#include "strv.h"
-const char *arg_target = NULL;
-bool arg_dry_run = false;
+static const char *arg_target = NULL;
+static bool arg_dry_run = false;
static int resize_ext4(const char *path, int mountfd, int devfd, uint64_t numblocks, uint64_t blocksize) {
assert((uint64_t) (int) blocksize == blocksize);
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index c607b5319b..28b830bd41 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -505,9 +505,9 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
path = strndupa(eq, e - eq);
bandwidth = e+1;
- if (streq(bandwidth, "infinity")) {
+ if (streq(bandwidth, "infinity"))
bytes = CGROUP_LIMIT_MAX;
- } else {
+ else {
r = parse_size(bandwidth, 1000, &bytes);
if (r < 0)
return log_error_errno(r, "Failed to parse byte value %s: %m", bandwidth);