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,
char *r_name;
int c, r, i = 0;
+ PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
assert(name);
assert(errnop);
assert(h_errnop);
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
if (r < 0) {
- if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
- *errnop = ESRCH;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
+ if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") ||
+ !bus_error_shall_fallback(&error))
+ goto not_found;
/* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails,
allowing falling back to other nss modules. Treat all other error conditions as
NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this
case so that the nsswitch.conf configuration can distuingish such executed but
negative replies from complete failure to talk to resolved). */
- if (!bus_error_shall_fallback(&error))
- ret = NSS_STATUS_NOTFOUND;
-
goto fail;
}
r = c;
goto fail;
}
- if (c == 0) {
- *errnop = ESRCH;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
+ if (c == 0)
+ goto not_found;
if (isempty(canonical))
canonical = name;
if (ttlp)
*ttlp = 0;
- /* Explicitly reset all error variables */
- *errnop = 0;
+ /* Explicitly reset both *h_errnop and h_errno to work around
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
*h_errnop = NETDB_SUCCESS;
h_errno = 0;
*errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
+
+not_found:
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
}
enum nss_status _nss_resolve_gethostbyname3_r(
const char *canonical;
int c, r, i = 0;
+ PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
assert(name);
goto fail;
}
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
if (r < 0) {
- if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
- *errnop = ESRCH;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
-
- if (!bus_error_shall_fallback(&error))
- ret = NSS_STATUS_NOTFOUND;
+ if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") ||
+ !bus_error_shall_fallback(&error))
+ goto not_found;
goto fail;
}
r = c;
goto fail;
}
- if (c == 0) {
- *errnop = ESRCH;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
+ if (c == 0)
+ goto not_found;
if (isempty(canonical))
canonical = name;
result->h_length = alen;
result->h_addr_list = (char**) r_addr_list;
- /* Explicitly reset all error variables */
- *errnop = 0;
- *h_errnop = NETDB_SUCCESS;
- h_errno = 0;
-
if (ttlp)
*ttlp = 0;
if (canonp)
*canonp = r_name;
+ /* Explicitly reset both *h_errnop and h_errno to work around
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
+ *h_errnop = NETDB_SUCCESS;
+ h_errno = 0;
+
return NSS_STATUS_SUCCESS;
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
+
+not_found:
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
}
enum nss_status _nss_resolve_gethostbyaddr2_r(
const char *n;
int r, ifindex;
+ PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
assert(addr);
return NSS_STATUS_UNAVAIL;
}
+ if (avoid_deadlock()) {
+ r = -EDEADLK;
+ goto fail;
+ }
+
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
if (r < 0) {
- if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
- *errnop = ESRCH;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
-
- if (!bus_error_shall_fallback(&error))
- ret = NSS_STATUS_NOTFOUND;
+ if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") ||
+ !bus_error_shall_fallback(&error))
+ goto not_found;
goto fail;
}
if (r < 0)
return r;
- if (c <= 0) {
- *errnop = ESRCH;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
+ if (c <= 0)
+ goto not_found;
ms += ALIGN(len) + /* the address */
2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */
if (ttlp)
*ttlp = 0;
- /* Explicitly reset all error variables */
- *errnop = 0;
+ /* Explicitly reset both *h_errnop and h_errno to work around
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
*h_errnop = NETDB_SUCCESS;
h_errno = 0;
*errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
+
+not_found:
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
}
NSS_GETHOSTBYNAME_FALLBACKS(resolve);