From nobody@FreeBSD.org  Fri Jul 15 02:42:51 2011
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 018FA106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 15 Jul 2011 02:42:51 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id DBD148FC12
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 15 Jul 2011 02:42:50 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id p6F2goBI048737
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 15 Jul 2011 02:42:50 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id p6F2goEN048734;
	Fri, 15 Jul 2011 02:42:50 GMT
	(envelope-from nobody)
Message-Id: <201107150242.p6F2goEN048734@red.freebsd.org>
Date: Fri, 15 Jul 2011 02:42:50 GMT
From: lanxiaowei <lanxw@arraynetworks.com.cn>
To: freebsd-gnats-submit@FreeBSD.org
Subject: BPF element leak in ifp->bpf_if->bif_dlist
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         158930
>Category:       kern
>Synopsis:       [bpf] BPF element leak in ifp->bpf_if->bif_dlist
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-net
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jul 15 02:50:07 UTC 2011
>Closed-Date:    
>Last-Modified:  Mon Jul 25 07:50:09 UTC 2011
>Originator:     lanxiaowei
>Release:        bsd7.0
>Organization:
arraynetworks
>Environment:
FreeBSD dev170-04.arraynetworks.net 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Sun Feb 24 10:35:36 UTC 2008     root@driscoll.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  amd64

>Description:
when i send arp repeatedly in userland by BPF, i find:
when the data flow is large, the performance will be very slow.
for example: if i dont' send arp, the data flow can reach 3.5G,
if i send arp, the data flow can only reach 1.5G.

Finally, i find the reason:
the BPF will leak some device in ifp->bpf_if->bif_dlist, so the system will capture passing packets in ETHER_BPF_MTAP!  
>How-To-Repeat:
1. run daemon
userland code:
AN# cat a.c
#include <sys/types.h> 
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <net/if.h>
#include <net/bpf.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int
open_bpf(char *ifname)
{
        struct ifreq ifr;
        int fd, n = 0;
        char device[sizeof "/dev/bpf000"];

        /*
         * Go through all the minors and find one that isn't in use.
         */
        do {
                (void)sprintf(device, "/dev/bpf%d", n++);
                fd = open(device, O_RDWR);
        } while (fd < 0 && errno == EBUSY && n < 100);

        if (fd < 0) {
                return -1;
        }

        (void)strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
        if (ioctl(fd, BIOCSETIF, (caddr_t) &ifr) < 0) {
                return -1;
        }

        return fd;
}




main()
{
int fd;
char buf[3333];
int len=3332;
while(1){
fd = open_bpf("em0");
        if (fd < 0) {
        return -1;
}

len = write(fd, buf, len);
close(fd);
sleep(10);
}
}

2.kgdb /kernel /dev/mem
(kgdb) p bpf_bpfd_cnt
$1 = 8 (it will increase, so it's a leak!)
>Fix:
in devfs_close(), i found the fd can't correctly closed.:
	if (vp->v_iflag & VI_DOOMED) {
		/* Forced close. */
	} else if (dsw->d_flags & D_TRACKCLOSE) {
		/* Keep device updated on status. */
	} else if (count_dev(dev) > 1) {<----------------it go into this case!
		VI_UNLOCK(vp);
		dev_relthread(dev);
		return (0);
	}



i don't know why it go into this case when close BPF device, so it don't call
bpfclose() to remove the BPF device from ifp->bpf_if->bif_dlist.


thanks.

Test case attached with submission follows:

#include <sys/types.h> 
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <net/if.h>
#include <net/bpf.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int
open_bpf(char *ifname)
{
	struct ifreq ifr;
	int fd, n = 0;
	char device[sizeof "/dev/bpf000"];

	/*
	 * Go through all the minors and find one that isn't in use.
	 */
	do {
		(void)sprintf(device, "/dev/bpf%d", n++);
		fd = open(device, O_RDWR);
	} while (fd < 0 && errno == EBUSY && n < 100);

	if (fd < 0) {
		return -1;
	}

	(void)strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
	if (ioctl(fd, BIOCSETIF, (caddr_t) &ifr) < 0) {
		return -1;
	}

	return fd;
}




main()
{
int fd;
char buf[3333];
int len=3332;
while(1){
fd = open_bpf("em0");
	if (fd < 0) {
	return -1;
}

len = write(fd, buf, len);
close(fd);
sleep(10);
}
}


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Fri Jul 15 04:44:31 UTC 2011 
Responsible-Changed-Why:  
Over to maintainer(s). 

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

From: "lanxw" <lanxw@arraynetworks.com.cn>
To: "bug-followup" <bug-followup@FreeBSD.org>,
 "lanxw" <lanxw@arraynetworks.com.cn>
Cc:  
Subject: Re: kern/158930: [bpf] BPF element leak in ifp-
Date: Mon, 25 Jul 2011 15:27:51 +0800

 This is a multi-part message in MIME format.
 
 --=====003_Dragon261518268670_=====
 Content-Type: text/plain;
 	charset="us-ascii"
 Content-Transfer-Encoding: 7bit
 
 i think in sending packet case, the BFD device should not be inserted into ifp->bpf_if->bif_dlist list.
 anybody know this?
 thanks a lot!
 
 2011-07-25 
 
 
 
 lanxw 
 
 --=====003_Dragon261518268670_=====
 Content-Type: text/html;
 	charset="us-ascii"
 Content-Transfer-Encoding: 7bit
 
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <HTML><HEAD>
 <META content="text/html; charset=us-ascii" http-equiv=Content-Type>
 <META name=GENERATOR content="MSHTML 8.00.6001.19088"><LINK rel=stylesheet 
 href="BLOCKQUOTE{margin-Top: 0px; margin-Bottom: 0px; margin-Left: 2em}"></HEAD>
 <BODY style="MARGIN: 10px; FONT-FAMILY: verdana; FONT-SIZE: 10pt">
 <DIV><FONT size=2 face=Verdana>i think in sending packet case, the BFD device 
 should not be inserted into ifp-&gt;bpf_if-&gt;bif_dlist list.</FONT></DIV>
 <DIV>anybody know this?</DIV>
 <DIV>thanks a lot!</DIV>
 <DIV><FONT size=2 face=Verdana></FONT>&nbsp;</DIV>
 <DIV align=left><FONT color=#c0c0c0 size=2 face=Verdana>2011-07-25 
 </FONT></DIV><FONT size=2 face=Verdana>
 <HR style="WIDTH: 122px; HEIGHT: 2px" align=left SIZE=2>
 
 <DIV><FONT color=#c0c0c0 size=2 face=Verdana><SPAN>lanxw</SPAN> 
 </FONT></DIV></FONT></BODY></HTML>
 
 --=====003_Dragon261518268670_=====--
 
>Unformatted:
