nss: never become IPC clients for services that are about to be started
This is an attempt to automatically detect and avoid certain kinds of NSS deadlocks as discussed in this thread: https://lists.freedesktop.org/archives/systemd-devel/2018-July/040975.html
This commit is contained in:
parent
3992221767
commit
2f28018cb8
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue