[MaraDNS] MaraDNS update (December 14, 2014)

Sam Trenholme maradns at gmail.com
Sun Dec 14 09:09:22 PST 2014

I have fixed two bugs in Deadwood, and am making a statement about
CERT vulnerability VU#264212 (Summary: MaraDNS is not vulnerable)

==Two bugs in Deadwood fixed==

Sten Kultakangas pointed out that MaraDNS sends the wrong ID when
sending a SERVER FAIL message. After working with him to recreate the
bug, and an hour of hunting, I have determined this is not a security

Deadwood takes the DNS packet it gets, performs some sanity checks on
it, changes its ID and RD bit, and then sends it to the upstream
server. This is fine in normal usage.

However, in the unusual case of giving a SERVER FAIL back to the
calling DNS thingy (because of high load, etc.), it sends back the
packet it sent upstream instead of sending back the packet the DNS
thingy sent Deadwood, causing the query ID mismatch.

When looking over this bug, I found another bug: If there is a
glueless NS record, Deadwood starts processing the NS referral, but
sends a server fail to the DNS thingy (instead of sending nothing
until the NS record is worked out).

I have also fixed this bug.

==Statement on CERT VU#264212==

MaraDNS is not vulnerable to the issue described in CERT VU#264212

Apparently, some DNS servers will follow glueless NS referrals without
end. Deadwood stops after 32 of those (probably a bit high, but
resolving names was the priority when I made that code) and MaraDNS
1.0 stops after 10 of those.

Here is the relevant code in DwRecurse.c (MaraDNS 2 / Deadwood):

/* Create a new outgoing query to process a glueless request (NS or CNAME);
 * similiar to forward_local_udp_packet() and make_new_udp_connect()
void dwx_do_glueless_new(dw_str *query, int32_t conn_number, int type) {
        if(rem[conn_number].recurse_depth > 32) {
        rem[new_conn_num].recurse_depth = rem[conn_number].recurse_depth + 1;

Likewise, the relevant code in MaraDNS 1.0:

int recurse_call(int id, int sock, struct sockaddr_in client,
                 js_string *query, int queries_sent, int glueless_level,
                 uint32 *ipret, js_string *ptrret) {
    /* Make sure we haven't overloaded the recursion depth or maximum glueless
       level */
    if(queries_sent > max_queries_total ||
       glueless_level > max_glueless_level) {
        if(rlog_level >= 4) {
            printf(" queries_total/glueless_level exceeded\n");
        return JS_ERROR;

More information about the List mailing list