On 27/08/17 08:18, Christian Kujau wrote:
OK, so I should have done this in the first place and used git bisect to
find out which commit in Dnsmasq introduced this behaviour:

  fa78573778cb23337f67f5d0c9de723169919047 is the first bad commit
  commit fa78573778cb23337f67f5d0c9de723169919047
  Author: Simon Kelley <si...@thekelleys.org.uk>
  Date:   Fri Jul 22 20:56:01 2016 +0100

     Zero packet buffers before building output, to reduce risk
     of information leakage.

Hi Christian,

Thanks for all your investigation and info so far. I too can now crash dnsmasq at will :-) So putting my novice C and even more novice gdb to work I've come up with what I feel is a slightly less invasive mitigation to the problem....which in essence is 'we've been sent a query but not yet allocated any buffer to it/updated the header limit offset but we pass a non zero query length. The result is we try to clear the memory before our buffer.

My workaround is to only call memset if the difference between buffer begin and buffer limit is bigger than the query length, thus it retains Simon's intent of clearing memory most of the time but avoids the SIGSEGV trampling.

This is to be regarded as a sticking plaster rather than real fix but that needs far greater minds than I to understand the code & intent :-)

Hope this helps someone.


>From 340a26f915d8c3bb54c44f58d432cc7240631a74 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ke...@darbyshire-bryant.me.uk>
Date: Mon, 28 Aug 2017 14:52:10 +0100
Subject: [PATCH] dnsmasq: rfc1035: mitigate CVE-2017-13704

Work around a problem where answer_request() attempts to clear from the
end of a request to end of request buffer but the end of the buffer is
at the same place as the start.

Originally this meant that memset() tried to clear data before the
buffer leading to segmentation violation.  Instead only clear to end of
buffer it is bigger than the request length.

Signed-off-by: Kevin Darbyshire-Bryant <ke...@darbyshire-bryant.me.uk>
 src/rfc1035.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/rfc1035.c b/src/rfc1035.c
index 26f5301..91a9641 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1225,7 +1225,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
   /* Clear buffer beyond request to avoid risk of
      information disclosure. */
-  memset(((char *)header) + qlen, 0, 
+  if ( (limit - ((char *)header)) > qlen )
+      memset(((char *)header) + qlen, 0,
 	 (limit - ((char *)header)) - qlen);
   if (ntohs(header->ancount) != 0 ||

Dnsmasq-discuss mailing list

Reply via email to