Date: 11 Mar 2000 07:14:15 -0000 From: patrick@mindstep.com To: freefall-gnats@mindstep.com Subject: kern/17311: bug in the code handling ioctl SIOCGIFCONF Message-ID: <20000311071415.26789.qmail@modemcable127.61-201-24.mtl.mc.videotron.net>
next in thread | raw e-mail | index | archive | help
>Number: 17311 >Category: kern >Synopsis: bug in the code handling ioctl SIOCGIFCONF >Confidential: no >Severity: critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Mar 10 23:20:01 PST 2000 >Closed-Date: >Last-Modified: >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: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000311071415.26789.qmail>