BUG/MEDIUM: resolvers: Remove aborted resolutions from query_ids tree
To avoid any UAF when a resolution is released, a mechanism was added to
abort a resolution and delayed the released at the end of the current
execution path. This mechanism depends on an hard assumption: Any reference
on an aborted resolution must be removed. So, when a resolution is aborted,
it is removed from the resolver lists and inserted into a death row list.
However, a resolution may still be referenced in the query_ids tree. It is
the tree containing all resolutions with a pending request. Because aborted
resolutions are released outside the resolvers lock, it is possible to
release a resolution on a side while a query ansswer is received and
processed on another one. Thus, it is still possible to have a UAF because
of this bug.
To fix the issue, when a resolution is aborted, it is removed from any list,
but it is also removed from the query_ids tree.
This patch should solve the issue #1862 and may be related to #1875. It must
be backported as far as 2.2.
(cherry picked from commit eaabf060312f6aad1c0c195ad33e5ea612acc47a)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 4d4abc49b30a245e0f79de174101bd1ace91fced)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit c29a0d0c8f4ba0055659ac45c4a48401ca923c54)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/resolvers.c b/src/resolvers.c
index 5f5b48f..1c7c9d8 100644
--- a/src/resolvers.c
+++ b/src/resolvers.c
@@ -595,6 +595,11 @@
/* Add a resolution to the death_row. */
static void abort_resolution(struct resolv_resolution *res)
{
+ /* Remove the resolution from query_ids tree and from any resolvers list */
+ eb32_delete(&res->qid);
+ res->query_id = 0;
+ res->qid.key = 0;
+
LIST_DEL_INIT(&res->list);
LIST_APPEND(&death_row, &res->list);
}