Gabor Juhos írta:
> Bernhard Reutner-Fischer írta:
>> On Tue, Mar 23, 2010 at 09:18:21AM +0100, Gabor Juhos wrote:
>>> If the type of the first answer does not match with the requested type,
>>> then the dotted name will be freed. If there are no further answers in
>>> the DNS reply, this pointer will be used later on in the same function.
>>> Additionally it is passed to the caller, and may cause strange behaviour.
>>>
>>> For example, the following busybox commands are triggering a segmentation
>>> fault with uClibc 0.9.30.x
>> I cannot reproduce this with attached test program with 0.9.31-rc1 (or
>> current master)?
> 
> Thanks for your response.
> 
> Unfortunately your test program does not trigger the segmentation fault on
> 0.9.30.1. Now that 0.9.31 is out, i will try that.

Well, I did try that. Unfortunately, the bug is present in 0.9.31 as well.

With the attached patch, the bug is reproducible (on my system at least) even
with your test program.

Here is the screenshot:

r...@openwrt:/# gethostbyname ipv6.google.com
DNS query:
0000: 00 02 01 00 00 01 00 00 00 00 00 00 04 69 70 76
0010: 36 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 01 00
0020: 01

DNS response:
0000: 00 02 81 80 00 01 00 01 00 01 00 00 04 69 70 76
0010: 36 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 01 00
0020: 01 c0 0c 00 05 00 01 00 00 11 49 00 09 04 69 70
0030: 76 36 01 6c c0 11 c0 32 00 06 00 01 00 00 00 3c
0040: 00 26 03 6e 73 34 c0 11 09 64 6e 73 2d 61 64 6d
0050: 69 6e c0 11 00 15 89 61 00 00 03 84 00 00 03 84
0060: 00 00 07 08 00 00 00 3c

Oops! Using bad address in gethostbyname_r at line 2223
Bus error
r...@openwrt:/#

Regards,
Gabor
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 056539f..8824e6a 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -355,6 +355,13 @@ Domain name in a message can be represented as either:
 #define ALIGN_ATTR __alignof__(double __attribute_aligned__ (sizeof(size_t)))
 #define ALIGN_BUFFER_OFFSET(buf) ((ALIGN_ATTR - ((size_t)buf % ALIGN_ATTR)) % 
ALIGN_ATTR)
 
+#define BADADDR                ((void *) 0xBAD0ADD0)
+#define check_bad_addr(_a)                                                     
        \
+       do {                                                                    
        \
+               if ((_a) == BADADDR)                                            
        \
+                       fprintf(stderr, "Oops! Using bad address in %s at line 
%d\n",   \
+                               __FUNCTION__, __LINE__);                        
        \
+       } while (0)
 
 /* Structs */
 struct resolv_header {
@@ -474,6 +481,21 @@ extern int __encode_answer(struct resolv_answer *a,
 extern void __open_nameservers(void) attribute_hidden;
 extern void __close_nameservers(void) attribute_hidden;
 
+static inline void dump_bytes(const char *label, unsigned char *buf, int len)
+{
+       int i;
+
+       fprintf(stderr, "%s\n", label);
+       for (i = 0; i < len; i++) {
+               if ((i % 16) == 0)
+                       fprintf(stderr, "%04x: ", i);
+               fprintf(stderr, "%02x ", buf[i]);
+               if (((i + 1) % 16) == 0 || (i + 1) == len)
+                       fprintf(stderr, "\n");
+       }
+       fprintf(stderr, "\n");
+}
+
 /*
  * Theory of operation.
  *
@@ -1381,6 +1403,8 @@ int attribute_hidden __dns_lookup(const char *name,
                }
                DPRINTF("Xmit packet len:%d id:%d qr:%d\n", packet_len, h.id, 
h.qr);
                /* no error check - if it fails, we time out on recv */
+
+               dump_bytes("DNS query:", packet, packet_len);
                send(fd, packet, packet_len, 0);
 
 #ifdef USE_SELECT
@@ -1432,6 +1456,7 @@ int attribute_hidden __dns_lookup(const char *name,
                packet_len = recv(fd, packet, PACKETSZ, MSG_DONTWAIT);
 #endif
 
+               dump_bytes("DNS response:", packet, packet_len);
                if (packet_len < HFIXEDSZ) {
                        /* too short!
                         * it's just a bogus packet from somewhere */
@@ -1519,6 +1544,7 @@ int attribute_hidden __dns_lookup(const char *name,
                                        break;
                                if (a->atype != type) {
                                        free(a->dotted);
+                                       a->dotted = BADADDR;
                                        continue;
                                }
                                a->add_count = h.ancount - j - 1;
@@ -2174,6 +2200,7 @@ int gethostbyname_r(const char *name,
                 * or CNAME of the host if it is different from the name
                 * we used to find it) */
                if (a.dotted && buflen > strlen(a.dotted)) {
+                       check_bad_addr(a.dotted);
                        strcpy(buf, a.dotted);
                        alias0 = buf;
                }
@@ -2193,6 +2220,7 @@ int gethostbyname_r(const char *name,
        i = TRY_AGAIN;
 
  free_and_ret:
+       check_bad_addr(a.dotted);
        free(a.dotted);
        free(packet);
        return i;
@@ -2319,6 +2347,7 @@ int gethostbyname2_r(const char *name,
                        *h_errnop = HOST_NOT_FOUND;
                        return TRY_AGAIN;
                }
+               check_bad_addr(a.dotted);
                strncpy(buf, a.dotted, buflen);
                free(a.dotted);
 
@@ -2476,6 +2505,7 @@ int gethostbyaddr_r(const void *addr, socklen_t addrlen,
                        return TRY_AGAIN;
                }
 
+               check_bad_addr(a.dotted);
                strncpy(buf, a.dotted, buflen);
                free(a.dotted);
                if (a.atype != T_CNAME)
@@ -3117,6 +3147,7 @@ int res_query(const char *dname, int class, int type,
                return -1;
        }
 
+       check_bad_addr(a.dotted);
        free(a.dotted);
 
        if (a.atype == type) { /* CNAME */
_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to