<div>Hi,</div><div><br></div><div>I don't know if it's appropriate to discuss specific code here, but mesh_make_new_space() maybe is at risk under particular conditions.</div><div><br></div><div>when the mesh_state queue is full and new query comes in, one mesh_state will be kicked out which is happened in mesh_make_new_space() function, and call mesh_state_delete() function. mesh_state_delete() function will eventually call iter_clear(), iter_clear() will delete the outnet query of this mesh_state which is in function serviced_delete(). </div>
<div><br></div><div>serviced_delete() call outnet_send_wait_udp() which will re-send some queries failed to send out last time, in these code</div><div><div>outnet_send_wait_udp(struct outside_network* outnet)</div><div>{</div>
</div><div>...</div><div><div><span class="Apple-tab-span" style="white-space:pre">             </span>if(!randomize_and_send_udp(outnet, pend, outnet->udp_buff, </div><div><span class="Apple-tab-span" style="white-space:pre">                       </span>pend->timeout)) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                      </span>/* callback error on pending */</div><div><span class="Apple-tab-span" style="white-space:pre">                      </span>fptr_ok(fptr_whitelist_pending_udp(pend->cb));</div>
<div><span class="Apple-tab-span" style="white-space:pre">                      </span>(void)(*pend->cb)(outnet->unused_fds->cp, pend->cb_arg, </div><div><span class="Apple-tab-span" style="white-space:pre">                         </span>NETEVENT_CLOSED, NULL);</div>
<div><span class="Apple-tab-span" style="white-space:pre">                      </span>pending_delete(outnet, pend);</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div></div><div>}</div><div><br></div><div>if randomize_and_send_udp() fail again, then pend->cb() will be called and will eventually go to mesh_run() function, and in iterator module it probably return SERVFAIL immediately while it still take control of the thread, maybe like these code in processQueryTargets().</div>
<div><div>if(!target) {</div><div><span class="Apple-tab-span" style="white-space:pre">               </span>if(iq->num_target_queries==0 && iq->num_current_queries==0) {</div><div><span class="Apple-tab-span" style="white-space:pre">                  </span>if(delegpt_count_missing_targets(iq->dp) > 0) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                              </span>int qs = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                          </span>verbose(VERB_ALGO, "querying for next "</div><div><span class="Apple-tab-span" style="white-space:pre">                                    </span>"missing target");</div>
<div><span class="Apple-tab-span" style="white-space:pre">                              </span>if(!query_for_targets(qstate, iq, ie, id, </div><div><span class="Apple-tab-span" style="white-space:pre">                                   </span>1, &qs)) {</div><div><span class="Apple-tab-span" style="white-space:pre">                                       </span>return error_response(qstate, id,</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                              </span>LDNS_RCODE_SERVFAIL);<br><br></div></div><div>or these in  processQueryTargets()</div><div><div>                 if(iq->num_target_queries == 0) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                              </span>return processLastResort(qstate, iq, ie, id);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>}</div></div><div><br></div><div>
then error_response() use c->buffer to send packet, and the buffer is used by new query at the same time. after mesh_state_delete(), new query's qname will point to wrong packet, but qname_len is right.</div><div><br>
</div><div>I'd say it's not that easy to happen in online environment, but still possible in small probability.</div>