diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c index 8d6caa0ada..d56d3b4c21 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, @@ -102,6 +116,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; @@ -254,6 +273,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; @@ -424,6 +448,11 @@ enum nss_status _nss_mymachines_getpwnam_r( * running on the host. */ goto not_found; + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + r = sd_bus_open_system(&bus); if (r < 0) goto fail; @@ -505,6 +534,11 @@ enum nss_status _nss_mymachines_getpwuid_r( if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) goto not_found; + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + r = sd_bus_open_system(&bus); if (r < 0) goto fail; @@ -601,6 +635,11 @@ enum nss_status _nss_mymachines_getgrnam_r( if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) goto not_found; + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + r = sd_bus_open_system(&bus); if (r < 0) goto fail; @@ -679,6 +718,11 @@ enum nss_status _nss_mymachines_getgrgid_r( if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) goto not_found; + 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 eb3d2d977f..f67a28076c 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, @@ -116,6 +130,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; @@ -294,6 +313,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; @@ -484,6 +508,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;