From nobody@FreeBSD.org  Tue Aug  3 15:02:13 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 2B508106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  3 Aug 2010 15:02:13 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 0F0E58FC08
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  3 Aug 2010 15:02:13 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o73F2CQF016831
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 3 Aug 2010 15:02:12 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o73F2CL6016830;
	Tue, 3 Aug 2010 15:02:12 GMT
	(envelope-from nobody)
Message-Id: <201008031502.o73F2CL6016830@www.freebsd.org>
Date: Tue, 3 Aug 2010 15:02:12 GMT
From: Stef Walter <stef@memberwebs.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: struct ifm_data.ifi_datalen set to invalid value on 32-bit access to 64-bit kernel
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>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:    kib
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 03 15:10:03 UTC 2010
>Closed-Date:    Tue Aug 10 10:17:43 UTC 2010
>Last-Modified:  Tue Aug 10 10:20:04 UTC 2010
>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     root@a2.ams.npubs.net:/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:

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149240: commit references a PR
Date: Tue,  3 Aug 2010 15:40:56 +0000 (UTC)

 Author: kib
 Date: Tue Aug  3 15:40:42 2010
 New Revision: 210805
 URL: http://svn.freebsd.org/changeset/base/210805
 
 Log:
   Properly set ifi_datalen for compat32 struct if_data32.
   
   PR:	kern/149240
   Submitted by:	Stef Walter <stef memberwebs com>
   MFC after:	1 weeks
 
 Modified:
   head/sys/net/rtsock.c
 
 Modified: head/sys/net/rtsock.c
 ==============================================================================
 --- head/sys/net/rtsock.c	Tue Aug  3 15:32:08 2010	(r210804)
 +++ head/sys/net/rtsock.c	Tue Aug  3 15:40:42 2010	(r210805)
 @@ -1439,7 +1439,7 @@ copy_ifdata32(struct if_data *src, struc
  	CP(*src, *dst, ifi_addrlen);
  	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);
  	CP(*src, *dst, ifi_baudrate);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: linimon 
State-Changed-When: Wed Aug 4 02:23:35 UTC 2010 
State-Changed-Why:  
Set as MFC reminder. 


Responsible-Changed-From-To: freebsd-bugs->kib 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Aug 4 02:23:35 UTC 2010 
Responsible-Changed-Why:  

http://www.freebsd.org/cgi/query-pr.cgi?pr=149240 
State-Changed-From-To: patched->closed 
State-Changed-By: kib 
State-Changed-When: Tue Aug 10 10:17:27 UTC 2010 
State-Changed-Why:  
Committed to HEAD and RELENG_8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=149240 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149240: commit references a PR
Date: Tue, 10 Aug 2010 10:17:10 +0000 (UTC)

 Author: kib
 Date: Tue Aug 10 10:17:01 2010
 New Revision: 211139
 URL: http://svn.freebsd.org/changeset/base/211139
 
 Log:
   MFC r210805:
   Properly set ifi_datalen for compat32 struct if_data32.
   
   PR:	kern/149240
 
 Modified:
   stable/8/sys/net/rtsock.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cam/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
 
 Modified: stable/8/sys/net/rtsock.c
 ==============================================================================
 --- stable/8/sys/net/rtsock.c	Tue Aug 10 10:15:34 2010	(r211138)
 +++ stable/8/sys/net/rtsock.c	Tue Aug 10 10:17:01 2010	(r211139)
 @@ -1439,7 +1439,7 @@ copy_ifdata32(struct if_data *src, struc
  	CP(*src, *dst, ifi_addrlen);
  	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);
  	CP(*src, *dst, ifi_baudrate);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
