Fix a problem in overload handling.

Sending the same query repeatedly to a dnsmasq instance which
doesn't get replies from upstream will eventually hit the
hard limit on frec_src structures and start gettin REFUSED
replies. This is OK, except that since the queries are no longer
being forwarded, an upstream server coming back doesn't reset the
situation. If there is any other traffic, frec allocation will
eventually delete the timed-out frec and get things moving again,
but that's not guaranteed.

To fix this we explicitly delete the frec once timed out in this case.

Thanks to Filip Jenicek for noticing and characterising this problem.
This commit is contained in:
Simon Kelley
2022-09-09 12:53:49 +01:00
parent 4447d48bb9
commit c4b9bc63e0

View File

@@ -244,6 +244,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (!daemon->free_frec_src) if (!daemon->free_frec_src)
{ {
query_full(now, NULL); query_full(now, NULL);
/* This is tricky; if we're blasted with the same query
over and over, we'll end up taking this path each time
and never resetting until the frec gets deleted by
aging followed by the receipt of a different query. This
is a bit of a DoS vuln. Avoid by explicitly deleting the
frec once it expires. */
if (difftime(now, forward->time) >= TIMEOUT)
free_frec(forward);
goto reply; goto reply;
} }