BUG/MEDIUM: resolvers: Don't recursively perform requester unlink

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.
This commit is contained in:
Christopher Faulet 2021-10-29 10:38:15 +02:00
parent e76b4f055d
commit bce6db6c3c

View 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);