From 3cd62b71e684243026590c1f73ec24478f95b6fb Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Mon, 19 Feb 2024 12:05:34 +0100 Subject: [PATCH] Fix race condition crash When running resolver benchmark pipeline, a crash occurred: https://gitlab.isc.org/isc-projects/bind9-shotgun-ci/-/pipelines/163946 In the code we are doing a lookup, it fails (meaning there is no node with lookup name), we create the node and insert it and it fails. But dns_qp_insert can only return ISC_R_SUCCESS or ISC_R_EXISTS. So it must have been inserted in between. This is a race condition bug. The first lookup only requires a write lock and if the lookup failed the lock gets upgraded to a write lock and we insert the missing data. To fix the race condition bug, we need to do a lookup again after we have upgraded the lock to make sure it wasn't inserted in the mean time. --- lib/dns/qpdb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/dns/qpdb.c b/lib/dns/qpdb.c index eaba8055af..8ed465b182 100644 --- a/lib/dns/qpdb.c +++ b/lib/dns/qpdb.c @@ -1905,10 +1905,14 @@ dns__qpdb_findnodeintree(dns_qpdb_t *qpdb, dns_qp_t *tree, * Try to upgrade the lock and if that fails unlock then relock. */ TREE_FORCEUPGRADE(&qpdb->tree_lock, &tlocktype); - node = dns_qpdata_create(qpdb, name); - result = dns_qp_insert(tree, node, 0); - INSIST(result == ISC_R_SUCCESS); - dns_qpdata_unref(node); + result = dns_qp_lookup(tree, name, NULL, NULL, NULL, + (void **)&node, NULL); + if (result != ISC_R_SUCCESS) { + node = dns_qpdata_create(qpdb, name); + result = dns_qp_insert(tree, node, 0); + INSIST(result == ISC_R_SUCCESS); + dns_qpdata_unref(node); + } if (tree == qpdb->tree) { dns__qpzone_addwildcards(qpdb, name, true);