From dunstan@freebsd.czest.pl  Sat Feb 19 21:43:38 2005
Return-Path: <dunstan@freebsd.czest.pl>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 309B416A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 19 Feb 2005 21:43:38 +0000 (GMT)
Received: from freebsd.czest.pl (silver.iplus.pl [80.48.250.4])
	by mx1.FreeBSD.org (Postfix) with ESMTP id AA40943D2D
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 19 Feb 2005 21:43:36 +0000 (GMT)
	(envelope-from dunstan@freebsd.czest.pl)
Received: from freebsd.czest.pl (freebsd.czest.pl [80.48.250.4])
	by freebsd.czest.pl (8.12.10/8.12.9) with ESMTP id j1JLn89r051574
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 19 Feb 2005 21:49:09 GMT
	(envelope-from dunstan@freebsd.czest.pl)
Received: (from dunstan@localhost)
	by freebsd.czest.pl (8.12.10/8.12.9/Submit) id j1JLn8Mc051573;
	Sat, 19 Feb 2005 21:49:08 GMT
	(envelope-from dunstan)
Message-Id: <200502192149.j1JLn8Mc051573@freebsd.czest.pl>
Date: Sat, 19 Feb 2005 21:49:08 GMT
From: "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
Reply-To: "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] Local DoS from user-space in if_clone_list()
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         77748
>Category:       kern
>Synopsis:       [PATCH] Local DoS from user-space in if_clone_list()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    maxim
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Feb 19 21:50:09 GMT 2005
>Closed-Date:    Sun Feb 27 15:57:51 GMT 2005
>Last-Modified:  Sun Feb 27 15:57:51 GMT 2005
>Originator:     Wojciech A. Koszek
>Release:        FreeBSD 5.3-STABLE i386
>Organization:
>Environment:
System: FreeBSD dunstan.freebsd.czest.pl 5.3-STABLE FreeBSD 5.3-STABLE #0: Sat Feb 12 11:15:23 CET 2005 root@dunstan.freebsd.czest.pl:/usr/obj/usr/src/sys/HOME6 i386

--
kern.ostype: FreeBSD
kern.osrelease: 5.3-STABLE
kern.osrevision: 199506
kern.version: FreeBSD 5.3-STABLE #0: Sat Feb 12 11:15:23 CET 2005
   root@dunstan.freebsd.czest.pl:/usr/obj/usr/src/sys/HOME6
--
kern.ostype: FreeBSD
kern.osrelease: 6.0-CURRENT
kern.osrevision: 199506
kern.version: FreeBSD 6.0-CURRENT #2: Sat Feb 12 10:43:18 UTC 2005
    root@:/usr/obj/usr/src/sys/GENERIC
--
>Description:
Bug exists in /usr/src/sys/net/if_clone.c, function if_clone_list().
This function use arguments which has been transferred from user-space,
with only partial validation tests. Thus, user may send malicious data
causing system to crash (if_clone_list() is used when ioctl is called with
SIOCIFGCLONERS on open socket as file descriptor).

>How-To-Repeat:
Attached code [if_clone_test.c] should panic your kernel:

$ gcc if_clone_test.c -o if_clone_test
$ ./if_clone_test

>Fix:
Attached patch [diff.0.if_clone.c] corrects this problem (-STABLE and -CURRENT).
Patch should be tested.

--- diff.0.if_clone.c begins here ---
Patch against FreeBSD 5.3-STABLE, kern.osreldate: 503102.

diff -upr /usr/src/sys/net/if_clone.c src/sys/net/if_clone.c
--- /usr/src/sys/net/if_clone.c	Sat Feb 12 09:36:35 2005
+++ src/sys/net/if_clone.c	Sat Feb 19 20:25:21 2005
@@ -239,6 +239,9 @@ if_clone_list(struct if_clonereq *ifcr)
 	struct if_clone *ifc;
 	int buf_count, count, err = 0;
 
+	if (ifcr->ifcr_count < 0)
+		return (EINVAL);
+
 	IF_CLONERS_LOCK();
 	/*
 	 * Set our internal output buffer size.  We could end up not
--- diff.0.if_clone.c ends here ---

--- if_clone_test.c begins here ---
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/wait.h>

#include <net/if.h>
#include <netinet/in.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>

int
main ()
{
	int s = 0, error = 0;
	int x;
	struct if_clonereq clr;

	s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (s == -1)
		errx(1, "Couldn't create socket");

	clr.ifcr_count = -10;
	clr.ifcr_buffer = NULL;

	error = ioctl(s, SIOCIFGCLONERS, &clr);
	if (error != 0)
		errx(1, "Error while ioctl()");

	close(s);
	exit(EX_OK);
}
--- if_clone_test.c ends here ---


>Release-Note:
>Audit-Trail:

From: Maxim Konovalov <maxim@macomnet.ru>
To: "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
Cc: bug-followup@freebsd.org
Subject: Re: kern/77748: [PATCH] Local DoS from user-space in if_clone_list()
Date: Sun, 20 Feb 2005 10:49:55 +0300 (MSK)

 Hi Wojciech,
 
 Nice catch!  It seems with your patch we do not need a second check
 for ifcr->ifcr_count a bit later in the code.
 
 Index: if_clone.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/net/if_clone.c,v
 retrieving revision 1.5
 diff -u -r1.5 if_clone.c
 --- if_clone.c	10 Feb 2005 12:02:37 -0000	1.5
 +++ if_clone.c	20 Feb 2005 07:42:30 -0000
 @@ -239,6 +239,9 @@
  	struct if_clone *ifc;
  	int buf_count, count, err = 0;
 
 +	if (ifcr->ifcr_count < 0)
 +		return (EINVAL);
 +
  	IF_CLONERS_LOCK();
  	/*
  	 * Set our internal output buffer size.  We could end up not
 @@ -261,12 +264,6 @@
  		/* Just asking how many there are. */
  		goto done;
  	}
 -
 -	if (ifcr->ifcr_count < 0) {
 -		err = EINVAL;
 -		goto done;
 -	}
 -
  	count = (if_cloners_count < buf_count) ?
  	    if_cloners_count : buf_count;
 
 %%%
 
 -- 
 Maxim Konovalov

From: "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/77748: [PATCH] Local DoS from user-space in if_clone_list()
Date: Sun, 20 Feb 2005 12:17:36 +0000

 --PEIAKu/WMn1b1Hv9
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 On Sun, Feb 20, 2005 at 10:49:55AM +0300, Maxim Konovalov wrote:
 Hi Maxim,
 
 [..]
 > -
 > -	if (ifcr->ifcr_count < 0) {
 > -		err = EINVAL;
 > -		goto done;
 > -	}
 > -
 [..]
 
 Indeed - we don't need this. Sorry, I could look at it more carefully while
 writing this patch... As I see, your correction doesn't change function
 behaviour and it works for me.
 
 Attached patch [diff.1.if_clone.c] corrects problem and redundant check.
 
 Regards,
 -- 
 * Wojciech A. Koszek && dunstan@FreeBSD.czest.pl
 
 --PEIAKu/WMn1b1Hv9
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="diff.1.if_clone.c"
 
 Patch against FreeBSD 5.3-STABLE, kern.osreldate: 503102.
 
 diff -upr /usr/src/sys/net/if_clone.c src/sys/net/if_clone.c
 --- /usr/src/sys/net/if_clone.c	Sat Feb 19 21:57:31 2005
 +++ src/sys/net/if_clone.c	Sun Feb 20 11:08:10 2005
 @@ -239,6 +239,9 @@ if_clone_list(struct if_clonereq *ifcr)
  	struct if_clone *ifc;
  	int buf_count, count, err = 0;
  
 +	if (ifcr->ifcr_count < 0)
 +		return (EINVAL);
 +
  	IF_CLONERS_LOCK();
  	/*
  	 * Set our internal output buffer size.  We could end up not
 @@ -259,11 +262,6 @@ if_clone_list(struct if_clonereq *ifcr)
  	ifcr->ifcr_total = if_cloners_count;
  	if ((dst = ifcr->ifcr_buffer) == NULL) {
  		/* Just asking how many there are. */
 -		goto done;
 -	}
 -
 -	if (ifcr->ifcr_count < 0) {
 -		err = EINVAL;
  		goto done;
  	}
  
 
 --PEIAKu/WMn1b1Hv9--
State-Changed-From-To: open->patched 
State-Changed-By: maxim 
State-Changed-When: Thu Feb 24 13:15:01 GMT 2005 
State-Changed-Why:  
Fixed in HEAD, thanks! 


Responsible-Changed-From-To: freebsd-bugs->maxim 
Responsible-Changed-By: maxim 
Responsible-Changed-When: Thu Feb 24 13:15:01 GMT 2005 
Responsible-Changed-Why:  
MFC reminder. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=77748 
State-Changed-From-To: patched->closed 
State-Changed-By: maxim 
State-Changed-When: Sun Feb 27 15:57:28 GMT 2005 
State-Changed-Why:  
Fixed in RELENG_5. 

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