dnsproxy: Fix wrong domain len causing crash in memmove
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 23 May 2012 18:00:10 +0000 (15:00 -0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 28 May 2012 13:23:46 +0000 (16:23 +0300)
If host_len is 0, strlen(*ptr) will return 0 as well and domain_len will
have the wrong value (-1). This causes connman to crash with the
following backtrace:

connmand[13361]: ++++++++ backtrace ++++++++
connmand[13361]: #0  0x7f33a5e49140 in /lib/libpthread.so.0
connmand[13361]: #1  0x7f33a509ed80 in /lib/libc.so.6
connmand[13361]: #2  0x4671a8 in forward_dns_reply() at src/dnsproxy.c:1568
connmand[13361]: #3  0x46725a in udp_server_event() at src/dnsproxy.c:1706
connmand[13361]: #4  0x7f33a62e14a5 in /usr/lib/libglib-2.0.so.0
connmand[13361]: #5  0x7f33a62e17d8 in /usr/lib/libglib-2.0.so.0
connmand[13361]: #6  0x7f33a62e1bd2 in /usr/lib/libglib-2.0.so.0
connmand[13361]: #7  0x40dfa1 in main() at src/main.c:510
connmand[13361]: #8  0x7f33a4f8e455 in /lib/libc.so.6
connmand[13361]: +++++++++++++++++++++++++++

To reproduce this issue, we need to have a domain name set and make a
query for "". The easiest way to do so is to use the (wrong) git command
below:

git push :your.host.name

Make sure we calculate domain_len the right way. By guaranteeing
host_len and domain_len are >= we can also use memcpy() instead of
memmove().

src/dnsproxy.c

index 6a9b138..5c4099b 100644 (file)
@@ -1551,13 +1551,13 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,
                         */
                        ptr = reply + offset + sizeof(struct domain_hdr);
                        host_len = *ptr;
-                       domain_len = strlen((const char *)ptr) - host_len - 1;
+                       domain_len = strlen((const char *)ptr + host_len + 1);
 
                        /*
-                        * remove the domain name and replaced it by the end
+                        * remove the domain name and replace it by the end
                         * of reply.
                         */
-                       memmove(ptr + host_len + 1,
+                       memcpy(ptr + host_len + 1,
                                ptr + host_len + domain_len + 1,
                                reply_len - (ptr - reply + domain_len));