]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: dns: Don't lock the server lock in snr_check_ip_callback().
authorOlivier Houchard <ohouchard@haproxy.com>
Mon, 6 Nov 2017 16:30:28 +0000 (17:30 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 6 Nov 2017 17:34:42 +0000 (18:34 +0100)
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.

src/dns.c
src/server.c

index 1d12c842109b538b8185205af7c28af25208ea78..0f93f3ce5577eb4fc321b2bb56279154d28d9510 100644 (file)
--- 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;
                }
 
index adc9fd40ce5ea55e9217281130c81c69ab20e981..1a78fb334f472d5c45d11c2701d317e78c8c1d38 100644 (file)
@@ -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 <srv> and is up.
  * It returns a pointer to the first server found or NULL if <ip> 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;
 }