tcpdump mailing list archives

Re: Losing BPF's


From: Guy Harris <guy () alum mit edu>
Date: Mon, 19 Feb 2007 00:10:13 -0800

Jon Steel wrote:

I have found a potential bug in libpcap on OpenBSD and likely FreeBSD as
well. If you simultaneously open several programs that open pcap
connections, you can cause the system to lose track of some of its
BPF's. When you close all the pcap connections some of the BPF's may
report that they are still busy.

You can reproduce this problem by doing the following:

1. Get a copy of bpfmaker.c and bpfMaker.pl that have been attched.
2. run `gcc bpfmaker.c -o bpfmaker -lpcap`
3. run `perl bfpmaker.pl <name of your ethernet card>

This will simultaneously open several copies of bpfmaker and close them
in a loop and lets you compare the number of bpf's being used on your
system at the start and end of the program.

I think the problem is that two programs simultaneously opening a live
pcap connection may cause two bpf device files to point to the same BPF
in the OS,

If so, that's an OS bug. /dev/bpfN is supposed to open the Nth BPF device; a quick look at the OpenBSD bpfopen() appears to indicate that it does do that:

int
bpfopen(dev_t dev, int flag, int mode, struct proc *p)
{
        struct bpf_d *d;

        /* create on demand */
        if ((d = bpfilter_create(minor(dev))) == NULL)
                return (ENXIO);
        /*
         * Each minor can be opened by only one process.  If the requested
         * minor is in use, return EBUSY.
         */
        if (!D_ISFREE(d))
                return (EBUSY);

        /* Mark "free" and do most initialization. */
        d->bd_bufsize = bpf_bufsize;
        d->bd_sig = SIGIO;

        D_GET(d);

        return (0);
}

        ...

struct bpf_d *
bpfilter_lookup(int unit)
{
        struct bpf_d *bd;

        LIST_FOREACH(bd, &bpf_d_list, bd_list)
                if (bd->bd_unit == unit)
                        return (bd);
        return (NULL);
}

struct bpf_d *
bpfilter_create(int unit)
{
        struct bpf_d *bd;

        if ((bd = bpfilter_lookup(unit)) != NULL)
                return (bd);
        if ((bd = malloc(sizeof(*bd), M_DEVBUF, M_NOWAIT)) != NULL) {
                bzero(bd, sizeof(*bd));
                bd->bd_unit = unit;
                D_MARKFREE(bd);
                LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list);
        }
        return (bd);
}

or two BPF's in the OS to point to the same device file.

If by "device file" you mean /dev/bpfN file, if that happened, that would also be a bug. I don't see how that could happen, given the OpenBSD BPF code.

I can't reproduce this on OS X 10.4 - I get

        $ sudo ./bpfMaker.pl en1
        BPF's at startup:        0
        BPF's upon ending:        0

so it's not inherent to BPF (10.4's libpcap doesn't do any file locking on BPF devices - it relies on the opens being exclusive use, just as the libpcap on {Free,Net,Open,DragonFly}BSD do).

Are you certain that the loop in your script isn't missing any BPF processes, so that some are left running?
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


Current thread: