Bug 158930 - [bpf] BPF element leak in ifp->bpf_if->bif_dlist
Summary: [bpf] BPF element leak in ifp->bpf_if->bif_dlist
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: Lawrence Stewart
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-15 03:50 UTC by lanxiaowei
Modified: 2022-11-22 22:53 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description lanxiaowei 2011-07-15 03:50:07 UTC
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!

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);
}
}
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!)
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2011-07-15 05:44:31 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-net

Over to maintainer(s).
Comment 2 lanxiaowei 2011-07-25 08:27:51 UTC
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 
Comment 3 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 08:01:33 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 4 Xin LI freebsd_committer freebsd_triage 2022-11-22 22:53:06 UTC
I think this was fixed in svn r229898 (9a7e6bac47adc1bbff8a3cb38ff74bde8a2cc399) in 2012.