]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
more cycle checks.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Feb 2009 13:23:17 +0000 (13:23 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Feb 2009 13:23:17 +0000 (13:23 +0000)
fix for reentrant problem.

git-svn-id: file:///svn/unbound/trunk@1485 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iterator.c
services/mesh.c
services/outside_network.c

index fa41dc759fd8f9cadd7170ff3d92569e8d03abc6..ed54afe420004a3c86023ee38a95b4650bf02869 100644 (file)
@@ -1,3 +1,10 @@
+18 February 2009: Wouter
+       - more cycle detection. Also for target queries.
+       - fixup bug where during deletion of the mesh queries the callbacks
+         that were reentrant caused assertion failures. Keep the mesh in 
+         a reentrant safe state.  Affects libunbound, reload of server,
+         on quit and flush_requestlist.
+
 13 February 2009: Wouter
        - forwarder information now per-thread duplicated.
          This keeps it read only for speed, with no locking necessary.
index 878c5c92e850949b99257385be61a39ea9e47954..88873c15c637ee2b00ecb7c84c936810ee47e8f3 100644 (file)
@@ -459,15 +459,13 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
  * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does
  *     not need initialisation.
  * @param v: if true, validation is done on the subquery.
- * @param detcyc: if true, cycle detection is done on the subquery.
  * @return false on error (malloc).
  */
 static int
 generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, 
        uint16_t qclass, struct module_qstate* qstate, int id,
        struct iter_qstate* iq, enum iter_state initial_state, 
-       enum iter_state final_state, struct module_qstate** subq_ret, int v,
-       int detcyc)
+       enum iter_state final_state, struct module_qstate** subq_ret, int v)
 {
        struct module_qstate* subq = NULL;
        struct iter_qstate* subiq = NULL;
@@ -490,13 +488,11 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
        if(!v)
                qflags |= BIT_CD;
        
-       if(detcyc) {
-               fptr_ok(fptr_whitelist_modenv_detect_cycle(
-                       qstate->env->detect_cycle));
-               if((*qstate->env->detect_cycle)(qstate, &qinf, qflags, prime)){
-                       log_query_info(VERB_DETAIL, "cycle detected", &qinf);
-                       return 0;
-               }
+       fptr_ok(fptr_whitelist_modenv_detect_cycle(
+               qstate->env->detect_cycle));
+       if((*qstate->env->detect_cycle)(qstate, &qinf, qflags, prime)){
+               log_query_info(VERB_DETAIL, "cycle detected", &qinf);
+               return 0;
        }
 
        /* attach subquery, lookup existing or make a new one */
@@ -565,7 +561,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq,
         * the normal INIT state logic (which would cause an infloop). */
        if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, 
                qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
-               &subq, 0, 1)) {
+               &subq, 0)) {
                verbose(VERB_ALGO, "could not prime root");
                return 0;
        }
@@ -634,7 +630,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
         * redundant INIT state processing. */
        if(!generate_sub_request(stub_dp->name, stub_dp->namelen, 
                LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
-               QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 1)) {
+               QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) {
                verbose(VERB_ALGO, "could not prime stub");
                (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
                return 1; /* return 1 to make module stop, with error */
@@ -712,7 +708,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq,
                if(!generate_sub_request(s->rk.dname, s->rk.dname_len, 
                        ntohs(s->rk.type), ntohs(s->rk.rrset_class),
                        qstate, id, iq,
-                       INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
+                       INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
                        verbose(VERB_ALGO, "could not generate addr check");
                        return;
                }
@@ -747,7 +743,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
                iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
        if(!generate_sub_request(iq->dp->name, iq->dp->namelen, 
                LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,
-               INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
+               INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
                verbose(VERB_ALGO, "could not generate ns check");
                return;
        }
@@ -1094,7 +1090,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,
 {
        struct module_qstate* subq;
        if(!generate_sub_request(name, namelen, qtype, qclass, qstate, 
-               id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0))
+               id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0))
                return 0;
        if(subq) {
                struct iter_qstate* subiq = 
@@ -1729,7 +1725,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
                if(!generate_sub_request(qstate->qinfo.qname, 
                        qstate->qinfo.qname_len, qstate->qinfo.qtype,
                        qstate->qinfo.qclass, qstate, id, iq,
-                       INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
+                       INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
                        verbose(VERB_ALGO, "could not generate prime check");
                }
                generate_a_aaaa_check(qstate, iq, id);
index c7a0f837df30e43424da813e24c47fba5f4d1bea..10619e5552da7ee6c3ec498dc55e3cac9aec2a11 100644 (file)
@@ -191,7 +191,10 @@ static void
 mesh_delete_helper(rbnode_t* n, void* ATTR_UNUSED(arg))
 {
        struct mesh_state* mstate = (struct mesh_state*)n->key;
-       mesh_state_cleanup(mstate);
+       /* perform a full delete, not only 'cleanup' routine,
+        * because other callbacks expect a clean state in the mesh.
+        * For 're-entrant' calls */
+       mesh_state_delete(&mstate->s);
 }
 
 void 
index 4d627914504b79f44c634554970577c925a0e5d9..a5d2374b87b66502f2912c7ed081dcfdc5b46657 100644 (file)
@@ -1116,6 +1116,8 @@ serviced_delete(struct serviced_query* sq)
                        if(p->pc)
                                portcomm_loweruse(sq->outnet, p->pc);
                        pending_delete(sq->outnet, p);
+                       /* this call can cause reentrant calls back into the
+                        * mesh */
                        outnet_send_wait_udp(sq->outnet);
                } else {
                        struct waiting_tcp* p = (struct waiting_tcp*)