]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix intermittent memory leak in dns_resolver unit
authorOndřej Surý <ondrej@isc.org>
Tue, 13 Dec 2022 10:02:47 +0000 (11:02 +0100)
committerOndřej Surý <ondrej@isc.org>
Wed, 14 Dec 2022 09:48:06 +0000 (10:48 +0100)
A rdataset could have been left unassociated on the error path in the
resume_dslookup() in the dns_resolver unit.  Clone the rdataset after
the error check, so it's not cloned before we check whether we can make
further progress chasing DS records.

lib/dns/resolver.c

index bb68d6db586a767733e7fb06603dc6ca3bf9615d..02b527365c08813e76716f0ab4ef864610479c4e 100644 (file)
@@ -7213,8 +7213,6 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
        dns_resolver_t *res = NULL;
        dns_rdataset_t *nsrdataset = NULL;
        dns_rdataset_t nameservers;
-       dns_fixedname_t fixed;
-       dns_name_t *domain = NULL;
        unsigned int n;
        dns_fetch_t *fetch = NULL;
 
@@ -7278,29 +7276,25 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
                goto cleanup;
 
        default:
-               /* Get nameservers from fctx->nsfetch before we destroy it. */
-               dns_rdataset_init(&nameservers);
-               if (dns_rdataset_isassociated(&fetch->private->nameservers)) {
-                       dns_rdataset_clone(&fetch->private->nameservers,
-                                          &nameservers);
-                       nsrdataset = &nameservers;
-               }
-
-               /* Get domain from nsfetch before we destroy it. */
-               domain = dns_fixedname_initname(&fixed);
-               dns_name_copy(fetch->private->domain, domain);
-
                /*
                 * If the chain of resume_dslookup() invocations managed to
                 * chop off enough labels from the original DS owner name to
                 * reach the top of the namespace, no further progress can be
                 * made.  Interrupt the DS chasing process, returning SERVFAIL.
                 */
-               if (dns_name_equal(fctx->nsname, domain)) {
+               if (dns_name_equal(fctx->nsname, fetch->private->domain)) {
                        result = DNS_R_SERVFAIL;
                        goto cleanup;
                }
 
+               /* Get nameservers from fctx->nsfetch before we destroy it. */
+               dns_rdataset_init(&nameservers);
+               if (dns_rdataset_isassociated(&fetch->private->nameservers)) {
+                       dns_rdataset_clone(&fetch->private->nameservers,
+                                          &nameservers);
+                       nsrdataset = &nameservers;
+               }
+
                n = dns_name_countlabels(fctx->nsname);
                dns_name_getlabelsequence(fctx->nsname, 1, n - 1, fctx->nsname);
 
@@ -7308,10 +7302,10 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
 
                fetchctx_ref(fctx);
                result = dns_resolver_createfetch(
-                       res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset,
-                       NULL, NULL, 0, fctx->options, 0, NULL, task,
-                       resume_dslookup, fctx, &fctx->nsrrset, NULL,
-                       &fctx->nsfetch);
+                       res, fctx->nsname, dns_rdatatype_ns,
+                       fetch->private->domain, nsrdataset, NULL, NULL, 0,
+                       fctx->options, 0, NULL, task, resume_dslookup, fctx,
+                       &fctx->nsrrset, NULL, &fctx->nsfetch);
                if (result != ISC_R_SUCCESS) {
                        fetchctx_unref(fctx);
                        if (result == DNS_R_DUPLICATE) {