From patrick@mindstep.com  Fri Mar 10 23:14:28 2000
Return-Path: <patrick@mindstep.com>
Received: from modemcable127.61-201-24.mtl.mc.videotron.net (modemcable127.61-201-24.mtl.mc.videotron.net [24.201.61.127])
	by hub.freebsd.org (Postfix) with SMTP id 2F05F37B5CB
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 10 Mar 2000 23:14:26 -0800 (PST)
	(envelope-from patrick@mindstep.com)
Received: (qmail 26795 invoked by alias); 11 Mar 2000 07:14:17 -0000
Received: (qmail 26790 invoked by uid 1002); 11 Mar 2000 07:14:15 -0000
Message-Id: <20000311071415.26789.qmail@modemcable127.61-201-24.mtl.mc.videotron.net>
Date: 11 Mar 2000 07:14:15 -0000
From: patrick@mindstep.com
Reply-To: patrick@mindstep.com
To: freefall-gnats@mindstep.com
Subject: bug in the code handling ioctl SIOCGIFCONF
X-Send-Pr-Version: 3.2

>Number:         17311
>Category:       kern
>Synopsis:       bug in the code handling ioctl SIOCGIFCONF
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 10 23:20:01 PST 2000
>Closed-Date:    Sat Jun 10 07:30:18 PDT 2000
>Last-Modified:  Sat Jun 10 07:31:25 PDT 2000
>Originator:     Patrick Bihan-Faou
>Release:        FreeBSD 3.4-STABLE i386
>Organization:
MindStep Corporation
>Environment:

FreeBSD 3.4-STABLE and FreeBSD 4.0-CURRENT

>Description:

When invoked with a small buffer size, the ioctl SIOCGIFCONF may return
more information than can fit in the provided buffer.

This problem has been partially fixed in FreeBSD 4.0 (if.c rev 1.85). 
It does not write outside the boundary of the provided buffer but the 
returned buffer size is incorrect. This in turn can lead to problems 
in the calling code.

This only happens if the system has interfaces for which sa->sa_len is greater
than sizeof(*sa), which is the case with most non-IPv4 addresses...

This problem has been noted in PR kern/12996 and PR kern/14457 without
a good fix yet.


>How-To-Repeat:

The following piece of code will show the problem.



#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/sockio.h>

#define VERBOSE_CHECK
check55(char *start,char *end)
{
	int	startoff=-1,endoff=0;
	int	off=0,c=0;

#ifdef VERBOSE_CHECK
	printf("%03d\t",off);
#endif
	for(;start<end;start++,off++)
	{
		if(*start != 0x55)
		{
			if(startoff<0)
			{
				startoff=off;
			}
			endoff=off;
		}
#ifdef VERBOSE_CHECK
		if(++c>=33)
		{
			printf("\n%03d\t",off);
			c=1;
		}
		printf("%02x ",*(unsigned char*)start);
#endif
	}
	printf("\n");
	if(startoff>=0)
	{
		printf("	** buffer changed from %d to %d => %d bytes modified **\n",startoff,endoff, endoff - startoff + 1);
	}
}

main()
{
  struct ifconf ifc;
  char *x;
  struct ifreq *ifr;
  struct sockaddr_in *sin;
  int len,ret;
  int s;
  char buf[1024];
#define END_TEST	300
 
  if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
 
  for (len=1;len<=END_TEST;len++) {
    ifc.ifc_buf = buf;
    ifc.ifc_len = len;
	memset(buf,0x55,sizeof(buf));
	printf("\n");
	printf("[Try with len=%d]\n",len);
    if ((ret=ioctl(s,SIOCGIFCONF,&ifc)) < 0)
	{
		printf(" => ioctl failed (returned %d, errno=%d)\n",ret,errno);
	}
	printf(" => ioctl succeeded, pretends it wrote %d bytes\n",ifc.ifc_len);
	printf("\n");
	check55(buf,buf+sizeof(buf));
	printf("\n");
  }
  return 0;
}

>Fix:
	


Fix to apply against the HEAD of the CVS

Index: if.c
===================================================================
RCS file: /cvs/freebsd/src/sys/net/if.c,v
retrieving revision 1.85
diff -u -r1.85 if.c
--- if.c	2000/02/28 19:30:25	1.85
+++ if.c	2000/03/10 23:29:50
@@ -1086,11 +1086,9 @@
 						sizeof (ifr));
 				ifrp++;
 			} else {
-				if (space < sa->sa_len - sizeof(*sa))
+				if (space < sizeof(ifr) + sa->sa_len - sizeof(*sa))
 					break;
 				space -= sa->sa_len - sizeof(*sa);
-				if (space < sizeof (ifr))
-					break;
 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 						sizeof (ifr.ifr_name));
 				if (error == 0)






Fix to apply against the RELENG_3 branch of the CVS

Index: if.c
===================================================================
RCS file: /cvs/freebsd/src/sys/net/if.c,v
retrieving revision 1.64.2.3
diff -u -r1.64.2.3 if.c
--- if.c	2000/01/27 16:54:57	1.64.2.3
+++ if.c	2000/03/10 23:29:31
@@ -861,9 +861,9 @@
 						sizeof (ifr));
 				ifrp++;
 			} else {
-				space -= sa->sa_len - sizeof(*sa);
-				if (space < sizeof (ifr))
+				if (space < sizeof(ifr) + sa->sa_len - sizeof(*sa))
 					break;
+				space -= sa->sa_len - sizeof(*sa);
 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 						sizeof (ifr.ifr_name));
 				if (error == 0)


This PR should close PR kern/12996 and kern/14457



Patrick Bihan-Faou, Herve Masson
MindStep Corporation


>Release-Note:
>Audit-Trail:

From: Patrick Bihan-Faou <patrick@mindstep.com>
To: freebsd-gnats-submit@FreeBSD.org,
	Patrick Bihan-Faou <patrick@mindstep.com>
Cc:  
Subject: Re: kern/17311: bug in the code handling ioctl SIOCGIFCONF
Date: Sat, 11 Mar 2000 02:39:35 -0500

 The following test code will provide better report on the version of the bug
 present in the system.
 
 
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <sys/sockio.h>
 
 #define VERBOSE_CHECK
 int check55(char *start,char *end,int mod)
 {
 	int	startoff=-1,endoff=0;
 	int	off=0,c=0;
 int ret = 0;
 
 #ifdef VERBOSE_CHECK
 	printf("%03d\t",off);
 #endif
 	for(;start<end;start++,off++)
 	{
 		if(*start != 0x55)
 		{
 			if(startoff<0)
 			{
 				startoff=off;
 			}
 			endoff=off;
 		}
 #ifdef VERBOSE_CHECK
 		if(++c>=33)
 		{
 			printf("\n%03d\t",off);
 			c=1;
 		}
 		printf("%02x ",*(unsigned char*)start);
 #endif
 	}
 	printf("\n");
 	if(startoff>=0)
 	{
 		printf("	** buffer changed from %d to %d => %d bytes modified
 **\n",startoff,endoff, endoff - startoff + 1);
 if (mod != (endoff-startoff+1))
     ret = 1;
 
  }
 
 return ret;
 }
 
 main()
 {
   struct ifconf ifc;
   char *x;
   struct ifreq *ifr;
   struct sockaddr_in *sin;
   int len,ret;
   int s;
   char buf[1024];
   int bug=0;
 
 #define END_TEST	300
 
   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
 
   for (len=1;len<=END_TEST;len++) {
     ifc.ifc_buf = buf;
     ifc.ifc_len = len;
 	memset(buf,0x55,sizeof(buf));
 	printf("\n");
 	printf("[Try with len=%d]\n",len);
     if ((ret=ioctl(s,SIOCGIFCONF,&ifc)) < 0)
 	{
 		printf(" => ioctl failed (returned %d, errno=%d)\n",ret,errno);
 	}
 	printf(" => ioctl succeeded, pretends it wrote %d bytes\n",ifc.ifc_len);
 
 if ((ifc.ifc_len > len) && bug < 1)
 {
  bug = 1;
 }
  printf("\n");
 if(check55(buf,buf+sizeof(buf),ifc.ifc_len) && bug > 0)
 {
  bug = 2;
 }
  printf("\n");
   }
 
 switch (bug)
 {
     case 0:
         printf("\n\n*** Implementation OK (FIXED) *** \n\n");
         break;
     case 1:
         printf("\n\n*** Implementation returns incorrect ifc.ifc_len, but
 buffer OK (HEAD) ***\n\n");
         break;
     case 2:
         printf("\n\n*** Implementation corrupts buffer (RELENG_3) ***\n\n");
         break;
     default:
         printf("\n\n*** Huh ??? %d ***", bug);
         break;
 }
   return bug;
 }
 
 
 
State-Changed-From-To: open->feedback 
State-Changed-By: guido 
State-Changed-When: Fri Apr 21 19:54:23 MEST 2000 
State-Changed-Why:  
Please chck if rev. 1.86 of if.c (in 5.0-current) or rev 1.85.2.1 
(4.-stable) fixes it 


From: "Patrick Bihan-Faou" <patrick@mindstep.com>
To: <freebsd-gnats-submit@FreeBSD.org>,
	"Patrick Bihan-Faou" <patrick@mindstep.com>
Cc:  
Subject: Re: kern/17311: bug in the code handling ioctl SIOCGIFCONF
Date: Fri, 9 Jun 2000 18:17:20 -0400

 The bug is fixed.
 
 Patrick.
 
 
State-Changed-From-To: feedback->closed 
State-Changed-By: nrahlstr 
State-Changed-When: Sat Jun 10 07:30:18 PDT 2000 
State-Changed-Why:  
Originator reports that this is fixed. 


http://www.freebsd.org/cgi/query-pr.cgi?pr=17311 
>Unformatted:
