>Number:         149240
>Category:       kern
>Synopsis:       struct ifm_data.ifi_datalen set to invalid value on 32-bit 
>access to 64-bit kernel
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 03 15:10:03 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Stef Walter
>Release:        FreeBSD 8.1
>Organization:
>Environment:
FreeBSD a2.ams.npubs.net 8.1-RELEASE FreeBSD 8.1-RELEASE #4: Tue Aug  3 
14:31:11 UTC 2010     [email protected]:/usr/obj/usr/src/sys/RACK2  amd64
>Description:
The FreeBSD 32 compatibility layer sets the struct ifm_data.ifi_datalen member 
to the wrong value. ifi_datalen is supposed to contain the size of the ifm_data 
struct. The FreeBSD 32 compatibility code sets this to the sime of the 64-bit 
struct ifi_data rather than the 32-bit one.

This casues 32-bit applications using the sysctl() or PF_ROUTE style interfaces 
to access invalid memory, produce invalid results, and in many cases crash.
>How-To-Repeat:
/* Will produce invalid interface names when run as a 32-bit program on 64-bit 
*/
/* gcc -o test_iflist test_iflist.c */

#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>

#include <string.h>

int
main (void)
{
        char buffer[1024 * 64];
        char name[IFNAMSIZ];
        char *buf, *lim, *next;
        int mib[6];
        size_t length;
        struct if_msghdr *ifm, *nextifm;
        struct ifa_msghdr *ifam;
        struct sockaddr_dl *sdl;
        int addrcount;
        
        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
        mib[2] = 0;
        mib[3] = 0;                     /* address family */
        mib[4] = NET_RT_IFLIST;
        mib[5] = 0;

        length = sizeof (buffer);
        if (sysctl (mib, 6, buffer, &length, NULL, 0) < 0)
                err (1, "sysctl failed");

        buf = next = buffer;
        lim = buf + length;

        while (next < lim) {
                ifm = (struct if_msghdr*)next;
                if (ifm->ifm_type != RTM_IFINFO)
                        errx (1, "invalid ifm_type");

                if (ifm->ifm_data.ifi_datalen == 0)
                        ifm->ifm_data.ifi_datalen = sizeof(struct if_data);
                sdl = (struct sockaddr_dl *)((char *)ifm + 
                        sizeof(struct if_msghdr) -
                        sizeof(struct if_data) +
                        ifm->ifm_data.ifi_datalen);


                if (sdl->sdl_nlen >= sizeof (name))
                        err (1, "name too long");
                strncpy (name, sdl->sdl_data, sdl->sdl_nlen);
                
                next += ifm->ifm_msglen;
                warnx ("interface %d %s", ifm->ifm_index, name);        

                ifam = NULL;
                addrcount = 0;
                while (next < lim) {
                        nextifm = (struct if_msghdr*)next;
                
                        if (nextifm->ifm_type != RTM_NEWADDR)
                                break;
                
                        if (ifam == NULL)
                                ifam = (struct ifa_msghdr *)nextifm;
 
                        addrcount++;
                        next += nextifm->ifm_msglen;
                }
        }

        return 0;
}
>Fix:
Patch attached

Patch attached with submission follows:

--- ./sys/net/rtsock.c.orig     2010-08-03 14:19:14.000000000 +0000
+++ ./sys/net/rtsock.c  2010-08-03 14:20:54.000000000 +0000
@@ -1440,5 +1440,5 @@ copy_ifdata32(struct if_data *src, struc
        CP(*src, *dst, ifi_hdrlen);
        CP(*src, *dst, ifi_link_state);
-       CP(*src, *dst, ifi_datalen);
+       dst->ifi_datalen = sizeof(struct if_data32);
        CP(*src, *dst, ifi_mtu);
        CP(*src, *dst, ifi_metric);


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to