NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/39345: buffer overflow in dhcpcd leading to incorrect hardware address information



>Number:         39345
>Category:       bin
>Synopsis:       buffer overflow in dhcpcd leading to incorrect hardware 
>address information
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Aug 12 23:15:00 +0000 2008
>Originator:     Taylor R Campbell <campbell%mumble.net@localhost>
>Release:        NetBSD 4.99.72
>Organization:
>Environment:
System: NetBSD icon.localdomain 4.99.72 NetBSD 4.99.72 (RIAXEN3_DOMU) #6: Sat 
Aug  9 03:34:22 UTC 2008  
riastradh%smalltalk.localdomain@localhost:/home/riastradh/netbsd/current/obj/sys/arch/i386/compile/RIAXEN3_DOMU
 i386
Architecture: i386
Machine: i386
>Description:

        `do_interface' in net.c of dhcpcd statically allocates a struct
        sockaddr_dl and copies sizeof(struct sockaddr_dl) bytes into it
        from a struct ifreq's ifr_addr.  Then it copies into a buffer
        for the hardware address as many bytes as the sockaddr_dl's
        sdl_alen specifies, which may exceed the bounds of the
        statically allocated struct sockaddr_dl, leading to random
        bytes at the end of the hardware address.

>How-To-Repeat:

        When I run dhcpcd to configure an interface, it chooses a
        random last byte of the hardware address.  This sometimes leads
        to a failure to configure the interface by DHCP at all.

>Fix:

        Apply either of the following patches to
        src/external/bsd/dist/dhcpcd/dist/net.c:

--- net.c       27 Jul 2008 18:06:30 +0000      1.1.1.1
+++ net.c       12 Aug 2008 22:55:15 +0000      
@@ -197,7 +197,7 @@
        struct sockaddr_in netmask;
 
 #ifdef AF_LINK
-       struct sockaddr_dl sdl;
+       struct sockaddr_dl *sdl;
 #endif
 
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
@@ -244,10 +244,10 @@
 
 #ifdef AF_LINK
                if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) {
-                       memcpy(&sdl, &ifr->ifr_addr, sizeof(sdl));
-                       *hwlen = sdl.sdl_alen;
-                       memcpy(hwaddr, sdl.sdl_data + sdl.sdl_nlen,
-                              (size_t)sdl.sdl_alen);
+                       sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
+                       *hwlen = sdl->sdl_alen;
+                       memcpy(hwaddr, sdl->sdl_data + sdl->sdl_nlen,
+                              (size_t)sdl->sdl_alen);
                        retval = 1;
                        break;
                }

        The code originally copied the contents of the ifr_addr into a
        local buffer known to be aligned for a struct sockaddr_dl.  The
        above patch may cause access to misaligned struct fields;
        although I doubt this, the following patch avoids it.

--- net.c       27 Jul 2008 18:06:30 +0000      1.1.1.1
+++ net.c       12 Aug 2008 23:00:43 +0000      
@@ -197,7 +197,7 @@
        struct sockaddr_in netmask;
 
 #ifdef AF_LINK
-       struct sockaddr_dl sdl;
+       struct sockaddr_dl *sdl;
 #endif
 
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
@@ -244,10 +244,12 @@
 
 #ifdef AF_LINK
                if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) {
-                       memcpy(&sdl, &ifr->ifr_addr, sizeof(sdl));
-                       *hwlen = sdl.sdl_alen;
-                       memcpy(hwaddr, sdl.sdl_data + sdl.sdl_nlen,
-                              (size_t)sdl.sdl_alen);
+                       sdl = xmalloc(ifr->ifr_addr.sa_len);
+                       memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
+                       *hwlen = sdl->sdl_alen;
+                       memcpy(hwaddr, sdl->sdl_data + sdl->sdl_nlen,
+                              (size_t)sdl->sdl_alen);
+                       free(sdl);
                        retval = 1;
                        break;
                }



Home | Main Index | Thread Index | Old Index