From: Olivier Houchard Date: Mon, 6 Nov 2017 16:30:28 +0000 (+0100) Subject: BUG/MINOR: dns: Don't lock the server lock in snr_check_ip_callback(). X-Git-Tag: v1.8-rc3~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=283810773afa55dd50e6b362e2b93f8f7a88edc4;p=thirdparty%2Fhaproxy.git BUG/MINOR: dns: Don't lock the server lock in snr_check_ip_callback(). snr_check_ip_callback() may be called with the server lock, so don't attempt to lock it again, instead, make sure the callers always have the lock before calling it. --- diff --git a/src/dns.c b/src/dns.c index 1d12c84210..0f93f3ce55 100644 --- a/src/dns.c +++ b/src/dns.c @@ -1614,7 +1614,13 @@ static void dns_resolve_recv(struct dgram_conn *dgram) * from the cache */ tmpns = ns; list_for_each_entry(req, &res->requesters, list) { + struct server *s = objt_server(req->owner); + + if (s) + SPIN_LOCK(SERVER_LOCK, &s->lock); req->requester_cb(req, tmpns); + if (s) + SPIN_UNLOCK(SERVER_LOCK, &s->lock); tmpns = NULL; } diff --git a/src/server.c b/src/server.c index adc9fd40ce..1a78fb334f 100644 --- a/src/server.c +++ b/src/server.c @@ -3589,6 +3589,8 @@ int snr_update_srv_status(struct server *s, int has_no_ip) * returns: * 0 on error * 1 when no error or safe ignore + * + * Must be called with server lock held */ int snr_resolution_cb(struct dns_requester *requester, struct dns_nameserver *nameserver) { @@ -3694,7 +3696,9 @@ int snr_resolution_error_cb(struct dns_requester *requester, int error_code) s = objt_server(requester->owner); if (!s) return 1; + SPIN_LOCK(SERVER_LOCK, &s->lock); snr_update_srv_status(s, 0); + SPIN_UNLOCK(SERVER_LOCK, &s->lock); return 1; } @@ -3703,6 +3707,8 @@ int snr_resolution_error_cb(struct dns_requester *requester, int error_code) * which owns and is up. * It returns a pointer to the first server found or NULL if is not yet * assigned. + * + * Must be called with server lock held */ struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char *ip_family) { @@ -3712,8 +3718,6 @@ struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char if (!srv) return NULL; - SPIN_LOCK(SERVER_LOCK, &srv->lock); - be = srv->proxy; for (tmpsrv = be->srv; tmpsrv; tmpsrv = tmpsrv->next) { /* we found the current server is the same, ignore it */ @@ -3751,13 +3755,11 @@ struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char (tmpsrv->addr.ss_family == AF_INET6 && memcmp(ip, &((struct sockaddr_in6 *)&tmpsrv->addr)->sin6_addr, 16) == 0))) { SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock); - SPIN_UNLOCK(SERVER_LOCK, &srv->lock); return tmpsrv; } SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock); } - SPIN_UNLOCK(SERVER_LOCK, &srv->lock); return NULL; }