]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: resolvers: Don't recursively perform requester unlink
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 29 Oct 2021 08:38:15 +0000 (10:38 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 29 Oct 2021 13:06:31 +0000 (15:06 +0200)
When a requester is unlink from a resolution, by reading the code, we can
have this call chain:

_resolv_unlink_resolution(srv->resolv_requester)
  resolv_detach_from_resolution_answer_items(resolution, requester)
    resolv_srvrq_cleanup_srv(srv)
      _resolv_unlink_resolution(srv->resolv_requester)

A loop on the resolution answer items is performed inside
resolv_detach_from_resolution_answer_items(). But by reading the code, it
seems possible to recursively unlink the same requester.

To avoid any loop at this stage, the requester clean up must be performed
before the call to resolv_detach_from_resolution_answer_items(). This way,
the second call to _resolv_unlink_resolution() does nothing and returns
immediately because the requester was already detached from the resolution.

This patch is related to the issue #1404. It must be backported as far as
2.2.

src/resolvers.c

index a806f3397dfce84288af461d86bf6ad241278dab..5ed866b0869951f3a668581b116b61ec463e17ae 100644 (file)
@@ -2079,13 +2079,13 @@ static void _resolv_unlink_resolution(struct resolv_requester *requester)
                return;
        res = requester->resolution;
 
-       /* remove ref from the resolution answer item list to the requester */
-       resolv_detach_from_resolution_answer_items(res,  requester);
-
        /* Clean up the requester */
        LIST_DEL_INIT(&requester->list);
        requester->resolution = NULL;
 
+       /* remove ref from the resolution answer item list to the requester */
+       resolv_detach_from_resolution_answer_items(res,  requester);
+
        /* We need to find another requester linked on this resolution */
        if (!LIST_ISEMPTY(&res->requesters))
                req = LIST_NEXT(&res->requesters, struct resolv_requester *, list);