Race condition in bpfopen causes loss of bpf's

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Race condition in bpfopen causes loss of bpf's

Jonathan Steel-2
>Submitter-Id:  net
>Originator:   Jonathan Steel
>Organization: eSentire
net
>Synopsis:      Race condition in bpfopen causes loss of bpf's
>Severity:      serious
>Priority:      medium
>Category:      kernel
>Class:         sw-bug
>Release:       4.0
>Environment:
        System      : OpenBSD 4.0
        Architecture: OpenBSD.i386
        Machine     : i386
>Description:
    It is possilbe to lose bpf's by making a device /dev/bpfN file busy
when there are no programs using it. This is done by concurrently
execting programs that will open bpf connections such as anything that
uses libpcap.

    The pcap community wrote libpcap assuming that when you open a BPF
file (/dev/bfpN), it is locked at that point. But the kernel does not
actually do this, although I think it was intented to. Here is the
current code:

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);
}

In D_GET(), the macro D_MARKUSED is never called; In fact D_MARKUSED is
never called anywhere. This means that more than one process can open
the same /dev/bpfN file at the same time.

In pcap the files arent locked until the line "ioctl(fd, BIOCSETIF,
(caddr_t)&ifr);" is called. At this point, the line d->bd_next =
bp->bif_list in bpfattachd() has the side effect of locking the file.
But until then, mutltiple programs could grab the same file, eventually
leading to the loss of BPF's in the system.

>How-To-Repeat:

Open the same bpf file in two different programs and then call
"ioctl(fd, BIOCSETIF, (caddr_t)&ifr)";

This is done in the following code using pcap:

///////////////
// bpfmaker.c
///////////////
#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <signal.h>

// Opens a pcap connection to the given device and does nothing with
// the packets. Closes the pcap connection when the program
// is terminated.

char errBuf[PCAP_ERRBUF_SIZE];
pcap_t *sessionHandle;
void receivePacket(u_char *args, const struct pcap_pkthdr *header,
                   const u_char *packet);
void terminateOnSignal(int signal);

int main(int argc, char *argv[]) {
    int status;

    if (argc == 1) {
        fprintf(stderr, "Please provide the name of the ethernet device\n");
        return 1;
    }

    signal(SIGINT, terminateOnSignal);
    signal(SIGQUIT, terminateOnSignal);
    signal(SIGTRAP, terminateOnSignal);
    signal(SIGABRT, terminateOnSignal);
    signal(SIGTERM, terminateOnSignal);
    signal(SIGTERM, terminateOnSignal);

    sessionHandle = pcap_open_live(argv[1], 2000, 1, 1000, errBuf);

    if (sessionHandle == NULL) {
        fprintf(stderr, "Error opening pcap connection\n");
        return 2;
    }

    status = pcap_loop(sessionHandle, -1, receivePacket, NULL);

    fprintf(stderr, "Abnormal program termination\n");
}

void receivePacket(u_char *args, const struct pcap_pkthdr *header,
                   const u_char *packet) {
    return;
}

void terminateOnSignal(int signal) {
    fprintf(stderr, "Terminating bpf connection\n");

    if ( sessionHandle )
        pcap_close(sessionHandle);
    exit(99);
}


///////////////
// bpfmaker.pl
///////////////
#!/usr/bin/perl

if ($ARGV[0] eq "") {
    print "Please provide the name of the interface device\n";
    exit 1;
}

print "BPF's at startup: ";
system("cat /dev/bpf* 2>&1 | grep busy | wc -l");

for ($i = 0; $i < 4; $i++) {
    # creates a program to open a pcap connection
    system("./bpfmaker $ARGV[0] > $i&");
}

sleep 10;

# kills all the active bpfmaker programs
do {
    $pid = `ps ax | grep bpfmaker | grep -v grep | head -n 1`;
    $pid =~ m/(\d+).*/;
    $pid = $1;

    if ($pid) { `kill $pid` };
} while ($pid);

print "BPF's upon ending: ";
system("cat /dev/bpf* 2>&1 | grep busy | wc -l");

////////////////////////

Now run
1. 'gcc bpfmaker.c -o bpfmaker -lpcap'
2. 'perl bpfmaker.pl <name of ethernet device>

And you should get

Used BPF's at startup: <x>
Used BPF's upon ending: <x+1>

>Fix:
The solution as I see it is to do the following:
-call D_MARKUSED after the bpf has been obtained to lock the file
-obtain a lock around the call to bpfilter_create and the new call to
D_MARKUSED to prevent the race condition.

The lock is similar to what is currently done in FreeBSD. The code would
then be as follows in net/bpf.c:

struct lock bpf_lock;

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

    lockmgr(&bpf_lock, LK_EXCLUSIVE, NULL);

    /* create on demand */
    if ((d = bpfilter_create(minor(dev))) == NULL) {
        lockmgr(&bpf_lock, LK_RELEASE, 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)) {
        lockmgr(&bpf_lock, LK_RELEASE, NULL);
        return (EBUSY);
    }

    /* Mark 'used' so only one process can use device dev */
    D_MARKUSED(d);

    lockmgr(&bpf_lock, LK_RELEASE, NULL);

    /* Do most initialization. */
    d->bd_bufsize = bpf_bufsize;
    d->bd_sig = SIGIO;

    D_GET(d);

    return (0);
}

Reply | Threaded
Open this post in threaded view
|

Re: Race condition in bpfopen causes loss of bpf's

Otto Moerbeek
On Wed, 21 Feb 2007, Jon Steel wrote:

[snip]

> >Fix:
> The solution as I see it is to do the following:
> -call D_MARKUSED after the bpf has been obtained to lock the file
> -obtain a lock around the call to bpfilter_create and the new call to
> D_MARKUSED to prevent the race condition.
>
> The lock is similar to what is currently done in FreeBSD. The code would
> then be as follows in net/bpf.c:

Thanks for the diff.

I'm not a kernel hacker, so somebody else should check if this
generally acceptablel and the right type of lock is being used. But at
least you should initialize the bpf_lock struct somewhere.

        -Otto

>
> struct lock bpf_lock;
>
> int
> bpfopen(dev_t dev, int flag, int mode, struct proc *p)
> {
>     struct bpf_d *d;
>
>     lockmgr(&bpf_lock, LK_EXCLUSIVE, NULL);
>
>     /* create on demand */
>     if ((d = bpfilter_create(minor(dev))) == NULL) {
>         lockmgr(&bpf_lock, LK_RELEASE, 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)) {
>         lockmgr(&bpf_lock, LK_RELEASE, NULL);
>         return (EBUSY);
>     }
>
>     /* Mark 'used' so only one process can use device dev */
>     D_MARKUSED(d);
>
>     lockmgr(&bpf_lock, LK_RELEASE, NULL);
>
>     /* Do most initialization. */
>     d->bd_bufsize = bpf_bufsize;
>     d->bd_sig = SIGIO;
>
>     D_GET(d);
>
>     return (0);
> }

Reply | Threaded
Open this post in threaded view
|

Re: Race condition in bpfopen causes loss of bpf's

Thordur I. Bjornsson
In reply to this post by Jonathan Steel-2
Jon Steel <[hidden email]> wrote on Wed 21.Feb'07 at 11:31:04 -0500

<snip>
> >How-To-Repeat:
>
> Now run
> 1. 'gcc bpfmaker.c -o bpfmaker -lpcap'
> 2. 'perl bpfmaker.pl <name of ethernet device>
better not call it bpfmaker.pl it terminates unicely ;)
>
> And you should get
>
> Used BPF's at startup: <x>
> Used BPF's upon ending: <x+1>

I've not been able to reproduce with your regression test:
BPF's at startup:        1
Terminating bpf connection
Terminating bpf connection
Terminating bpf connection
Terminating bpf connection
BPF's upon ending:        1

On macppc:
OpenBSD 4.1-beta (GENERIC) #9: Thu Feb 22 23:18:41 GMT 2007
    [hidden email]:/usr/src/sys/arch/macppc/compile/GENERIC
and on i386:
OpenBSD 4.0-current (GENERIC) #1351: Wed Jan 24 20:29:10 MST 2007
    [hidden email]:/usr/src/sys/arch/i386/compile/GENERIC

This is confirmed with:
[root@trap /home/thib/bpf]$ sudo cat /dev/bpf*
cat: /dev/bpf0: Device busy
cat: /dev/bpf1: Device not configured
cat: /dev/bpf2: Device not configured
cat: /dev/bpf3: Device not configured
cat: /dev/bpf4: Device not configured
cat: /dev/bpf5: Device not configured
cat: /dev/bpf6: Device not configured
cat: /dev/bpf7: Device not configured
cat: /dev/bpf8: Device not configured
cat: /dev/bpf9: Device not configured

looks the same before and after I run the regression test.

Do you have a better regression test or am I doing sth wrong ?
I rewrote the diff to please otto since I forgot that dhclient takes
up one bpf :) and thought I was "leaking" bpf's ...
> >Fix:
Index: bpf.c
===================================================================
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.63
diff -u -p -r1.63 bpf.c
--- bpf.c 18 Jul 2006 11:52:12 -0000 1.63
+++ bpf.c 22 Feb 2007 23:03:01 -0000
@@ -51,6 +51,7 @@
 #include <sys/poll.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
+#include <sys/rwlock.h>
 
 #include <net/if.h>
 #include <net/bpf.h>
@@ -69,6 +70,9 @@
 int bpf_bufsize = BPF_BUFSIZE;
 int bpf_maxbufsize = BPF_MAXBUFSIZE;
 
+/* Serialize bpfopen calls */
+struct rwlock bpf_lock = RWLOCK_INITIALIZER;
+
 /*
  *  bpf_iflist is the list of interfaces; each corresponds to an ifnet
  *  bpf_d_list is the list of descriptors
@@ -326,15 +330,27 @@ bpfopen(dev_t dev, int flag, int mode, s
 {
  struct bpf_d *d;
 
+ rw_enter_write(&bpf_lock);
+
  /* create on demand */
- if ((d = bpfilter_create(minor(dev))) == NULL)
+ if ((d = bpfilter_create(minor(dev))) == NULL) {
+ rw_exit_write(&bpf_lock);
  return (ENXIO);
+ }
+
  /*
  * Each minor can be opened by only one process.  If the requested
  * minor is in use, return EBUSY.
  */
- if (!D_ISFREE(d))
+ if (!D_ISFREE(d)) {
+ rw_exit_write(&bpf_lock);
  return (EBUSY);
+ }
+
+ /* Mark 'used' so only one process can use device dev */
+ D_MARKUSED(d);
+
+ rw_exit_write(&bpf_lock);
 
  /* Mark "free" and do most initialization. */
  d->bd_bufsize = bpf_bufsize;

Reply | Threaded
Open this post in threaded view
|

Re: Race condition in bpfopen causes loss of bpf's

Otto Moerbeek
On Thu, 22 Feb 2007, Thordur I. Bjornsson wrote:

> Jon Steel <[hidden email]> wrote on Wed 21.Feb'07 at 11:31:04 -0500
>
> <snip>
> > >How-To-Repeat:
> >
> > Now run
> > 1. 'gcc bpfmaker.c -o bpfmaker -lpcap'
> > 2. 'perl bpfmaker.pl <name of ethernet device>
> better not call it bpfmaker.pl it terminates unicely ;)
> >
> > And you should get
> >
> > Used BPF's at startup: <x>
> > Used BPF's upon ending: <x+1>
>
> I've not been able to reproduce with your regression test:
> BPF's at startup:        1
> Terminating bpf connection
> Terminating bpf connection
> Terminating bpf connection
> Terminating bpf connection
> BPF's upon ending:        1

I cannot reproduce either on a MP amd64 and MP i386.

Jon, can you submit the dmesg of the machine you are using to show the
problem?

        -Otto

Reply | Threaded
Open this post in threaded view
|

Re: Race condition in bpfopen causes loss of bpf's

Otto Moerbeek
In reply to this post by Jonathan Steel-2
On Wed, 21 Feb 2007, Jon Steel wrote:

> # kills all the active bpfmaker programs
> do {
>     $pid = `ps ax | grep bpfmaker | grep -v grep | head -n 1`;
>     $pid =~ m/(\d+).*/;
>     $pid = $1;
>
>     if ($pid) { `kill $pid` };
> } while ($pid);

BTW, on my tests, this killed the perl process.... you gotta take care
with such kills. I 'solved' it by renaming the perl script.

        -Otto

Reply | Threaded
Open this post in threaded view
|

Re: Race condition in bpfopen causes loss of bpf's

Otto Moerbeek
On Fri, 23 Feb 2007, Otto Moerbeek wrote:

> On Wed, 21 Feb 2007, Jon Steel wrote:
>
> > # kills all the active bpfmaker programs
> > do {
> >     $pid = `ps ax | grep bpfmaker | grep -v grep | head -n 1`;
> >     $pid =~ m/(\d+).*/;
> >     $pid = $1;
> >
> >     if ($pid) { `kill $pid` };
> > } while ($pid);
>
> BTW, on my tests, this killed the perl process.... you gotta take care
> with such kills. I 'solved' it by renaming the perl script.

Oh, and btw there is a big fat race condition in your test. kill is
asynchronous, so it may very well be that your test if faulty.

        -Otto

Reply | Threaded
Open this post in threaded view
|

Re: Race condition in bpfopen causes loss of bpf's

Otto Moerbeek
On Fri, 23 Feb 2007, Jon Steel wrote:

> Otto Moerbeek wrote:
> > On Fri, 23 Feb 2007, Otto Moerbeek wrote:
> >
> >  
> >> On Wed, 21 Feb 2007, Jon Steel wrote:
> >>
> >>    
> >>> # kills all the active bpfmaker programs
> >>> do {
> >>>     $pid = `ps ax | grep bpfmaker | grep -v grep | head -n 1`;
> >>>     $pid =~ m/(\d+).*/;
> >>>     $pid = $1;
> >>>
> >>>     if ($pid) { `kill $pid` };
> >>> } while ($pid);
> >>>      
> >> BTW, on my tests, this killed the perl process.... you gotta take care
> >> with such kills. I 'solved' it by renaming the perl script.
> >>    
> >
> > Oh, and btw there is a big fat race condition in your test. kill is
> > asynchronous, so it may very well be that your test if faulty.
> >
> > -Otto
> >
> >  
> You can remove the race condition by adding a sleep before it does the
> kill loop. And sorry about the killing of the perl script, my script was
> actually named bpfMaker.pl.
>
> You may need to run the test several times. The one that I have provided
> you I usually need to run about 5 or 6 times. There are several ways to
> make it work better:
>
> 1. Increase the number of bpfs on your system and then make the loop
> open up like 400 at a time.
> 2. Put another loop around both the creating and killing loop and do it
> several times.
> 3. Increase the bandwidth on the connection being sniffed. This will
> cause the system to have more interrupts, making the race condition more
> likely.
>
> The only bulletproof way Ive found to lose exactly 1 packet every time
> is to actually modify the pcap library to sleep in certain spots to
> force the race condition (which shouldnt be possible even when trying to
> force it). Add a sleep of 15 seconds in the perl script before it kills
> off the bpfmakers. Then in libpcap, in the function pcap_open_live,
> right after the line "fd = bpf_open(p, ebuf);" (~= line 626 in
> pcap-bpf.c), add sleep(5). This will ensure all 8 programs have opened
> the same /dev/bpf file and then when they wake up and call "ioctl(fd,
> BIOCSETIF, (caddr_t)&ifr)" in the loop below, the problem will occure.
> You will lose exactly 1 bpf.
>
> Here is my dmesg (the only changes in GENERIC.MP.RAID are to set up a
> software raid. This problem also occurs on default kernels on the same
> box and on other boxes identical to it):

OK, with the extra sleep in libpcap I can reproduce the problem. Now
looking at the bpf code in the kernel to see how the bd_next field
actually is used to check if D_MARKUSED() won't interfere.  Also
sending this to bugs@, since other people might be interested or
wanting to help.

        -Otto

>
> OpenBSD 4.0 (GENERIC.MP.RAID) #0: Mon Jan 29 20:19:24 UTC 2007
>    
> [hidden email]:/usr/src/sys/arch/i386/compile/GENERIC.MP.RAID
> cpu0: Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz ("GenuineIntel" 686-class)
> 2.13 GHz
> cpu0:
> FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,SBF,SSE3,MWAIT,DS-CPL,VMX,EST,TM2,CX16
> real mem  = 2145869824 (2095576K)
> avail mem = 1948872704 (1903196K)
> using 4256 buffers containing 107397120 bytes (104880K) of memory
> mainbus0 (root)
> bios0 at mainbus0: AT/286+(7b) BIOS, date 10/30/06, BIOS32 rev. 0 @
> 0xfd470, SMBIOS rev. 2.51 @ 0x7feea000 (33 entries)
> bios0: Supermicro PDSMi
> pcibios0 at bios0: rev 2.1 @ 0xfd470/0xb90
> pcibios0: PCI BIOS has 20 Interrupt Routing table entries
> pcibios0: PCI Interrupt Router at 000:31:0 ("Intel 82801GB LPC" rev 0x00)
> pcibios0: PCI bus #15 is the last bus
> bios0: ROM list: 0xc0000/0xb000 0xcb000/0x1000 0xcc000/0x1000
> ipmi at mainbus0 not configured
> mainbus0: Intel MP Specification (Version 1.4) (INTEL    MUKILTEO    )
> cpu0 at mainbus0: apid 0 (boot processor)
> cpu0: unknown Core FSB_FREQ value 0 (0x42080000)
> cpu0: apic clock running at 266 MHz
> cpu1 at mainbus0: apid 1 (application processor)
> cpu1: Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz ("GenuineIntel" 686-class)
> 2.13 GHz
> cpu1:
> FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,SBF,SSE3,MWAIT,DS-CPL,VMX,EST,TM2,CX16
> mainbus0: bus 0 is type PCI
> mainbus0: bus 9 is type PCI
> mainbus0: bus 13 is type PCI
> mainbus0: bus 14 is type PCI
> mainbus0: bus 15 is type PCI
> mainbus0: bus 16 is type ISA
> ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 24 pins
> ioapic1 at mainbus0: apid 3 pa 0xfec10000, version 20, 24 pins
> pci0 at mainbus0 bus 0: configuration mode 1 (no bios)
> pchb0 at pci0 dev 0 function 0 "Intel E7230 MCH" rev 0xc0
> ppb0 at pci0 dev 1 function 0 "Intel E7230 PCIE" rev 0xc0
> pci1 at ppb0 bus 1
> ppb1 at pci0 dev 28 function 0 "Intel 82801GB PCIE" rev 0x01
> pci2 at ppb1 bus 9
> ppb2 at pci2 dev 0 function 0 "Intel PCIE-PCIE" rev 0x09
> pci3 at ppb2 bus 10
> "Intel IOxAPIC" rev 0x09 at pci2 dev 0 function 1 not configured
> ppb3 at pci0 dev 28 function 4 "Intel 82801G PCIE" rev 0x01
> pci4 at ppb3 bus 13
> em0 at pci4 dev 0 function 0 "Intel PRO/1000MT (82573E)" rev 0x03: apic
> 2 int 16 (irq 11), address 00:30:48:8b:c4:a6
> ppb4 at pci0 dev 28 function 5 "Intel 82801G PCIE" rev 0x01
> pci5 at ppb4 bus 14
> em1 at pci5 dev 0 function 0 "Intel PRO/1000MT (82573L)" rev 0x00: apic
> 2 int 17 (irq 11), address 00:30:48:8b:c4:a7
> uhci0 at pci0 dev 29 function 0 "Intel 82801GB USB" rev 0x01: apic 2 int
> 23 (irq 10)
> usb0 at uhci0: USB revision 1.0
> uhub0 at usb0
> uhub0: Intel UHCI root hub, rev 1.00/1.00, addr 1
> uhub0: 2 ports with 2 removable, self powered
> uhci1 at pci0 dev 29 function 1 "Intel 82801GB USB" rev 0x01: apic 2 int
> 19 (irq 11)
> usb1 at uhci1: USB revision 1.0
> uhub1 at usb1
> uhub1: Intel UHCI root hub, rev 1.00/1.00, addr 1
> uhub1: 2 ports with 2 removable, self powered
> uhci2 at pci0 dev 29 function 2 "Intel 82801GB USB" rev 0x01: apic 2 int
> 18 (irq 5)
> usb2 at uhci2: USB revision 1.0
> uhub2 at usb2
> uhub2: Intel UHCI root hub, rev 1.00/1.00, addr 1
> uhub2: 2 ports with 2 removable, self powered
> uhci3 at pci0 dev 29 function 3 "Intel 82801GB USB" rev 0x01: apic 2 int
> 16 (irq 11)
> usb3 at uhci3: USB revision 1.0
> uhub3 at usb3
> uhub3: Intel UHCI root hub, rev 1.00/1.00, addr 1
> uhub3: 2 ports with 2 removable, self powered
> ehci0 at pci0 dev 29 function 7 "Intel 82801GB USB" rev 0x01: apic 2 int
> 23 (irq 10)
> usb4 at ehci0: USB revision 2.0
> uhub4 at usb4
> uhub4: Intel EHCI root hub, rev 2.00/1.00, addr 1
> uhub4: 8 ports with 8 removable, self powered
> ppb5 at pci0 dev 30 function 0 "Intel 82801BA AGP" rev 0xe1
> pci6 at ppb5 bus 15
> vga1 at pci6 dev 0 function 0 "ATI ES1000" rev 0x02
> wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
> wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
> ichpcib0 at pci0 dev 31 function 0 "Intel 82801GB LPC" rev 0x01: PM disabled
> pciide0 at pci0 dev 31 function 1 "Intel 82801GB IDE" rev 0x01: DMA,
> channel 0 configured to compatibility, channel 1 configured to compatibility
> atapiscsi0 at pciide0 channel 0 drive 0
> scsibus0 at atapiscsi0: 2 targets
> cd0 at scsibus0 targ 0 lun 0: <TEAC, CD-224E-N, 1.AA> SCSI0 5/cdrom
> removable
> cd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
> pciide0: channel 1 disabled (no drives)
> pciide1 at pci0 dev 31 function 2 "Intel 82801GB SATA" rev 0x01: DMA,
> channel 0 configured to native-PCI, channel 1 configured to native-PCI
> pciide1: using apic 2 int 19 (irq 11) for native-PCI interrupt
> wd0 at pciide1 channel 0 drive 0: <WDC WD3200YS-01PGB0>
> wd0: 16-sector PIO, LBA48, 305245MB, 625142448 sectors
> wd0(pciide1:0:0): using PIO mode 4, Ultra-DMA mode 5
> wd1 at pciide1 channel 1 drive 0: <WDC WD2500JD-00HBB1>
> wd1: 16-sector PIO, LBA48, 238475MB, 488397168 sectors
> wd1(pciide1:1:0): using PIO mode 4, Ultra-DMA mode 5
> ichiic0 at pci0 dev 31 function 3 "Intel 82801GB SMBus" rev 0x01: apic 2
> int 19 (irq 11)
> iic0 at ichiic0
> lm1 at iic0 addr 0x2d: W83627HF
> "unknown" at iic0 addr 0x2f not configured
> isa0 at ichpcib0
> isadma0 at isa0
> pckbc0 at isa0 port 0x60/5
> pckbd0 at pckbc0 (kbd slot)
> pckbc0: using irq 1 for kbd slot
> wskbd0 at pckbd0: console keyboard, using wsdisplay0
> pmsi0 at pckbc0 (aux slot)
> pckbc0: using irq 12 for aux slot
> wsmouse0 at pmsi0 mux 0
> pcppi0 at isa0 port 0x61
> midi0 at pcppi0: <PC speaker>
> spkr0 at pcppi0
> lpt0 at isa0 port 0x378/4 irq 7
> lm0 at isa0 port 0x290/8: W83627HF
> lm1 detached
> npx0 at isa0 port 0xf0/16: using exception 16
> pccom0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
> pccom1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
> fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
> biomask 0 netmask 0 ttymask 0
> ioapic0: pin 16 shares different IPL interrupts (40..50), degraded
> performance
> pctr: 686-class user-level performance counters enabled
> mtrr: Pentium Pro MTRR support
> Kernelized RAIDframe activated
> dkcsum: wd0 matches BIOS drive 0x80
> dkcsum: wd1 matches BIOS drive 0x81
> root on wd0a
> rootdev=0x0 rrootdev=0x300 rawdev=0x302
> cpu1: unknown Core FSB_FREQ value 0 (0x42080000)
>
>
> Just as a question Thordur, how is rw_enter_write(&bpf_lock) atomic?
>
>
> Thanks