Hackers,

for the last couple of days i was able to crash my -current
laptop with "Fatal double fault" panic whenever i wanted.

i have created a small "spherical cow" :) to demonstrate 
the problem (see attached). this is pretty much what my code
does. just compile and load the "cow" and then try 

# ngctl msg cow: moo

i'm suspecting m_split() and have attached tiny path that
fixes problem for me.

of course it might be just my fault :) and i'm missing some
small thing.

"... if you think you found the bug - you don't... "

thanks,
max
/*
 * ng_cow.c
 *
 * Copyright (c) 2001-2002 Maksim Yevmenkin <[EMAIL PROTECTED]>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_parse.h>

#define NG_COW_NODE_TYPE        "cow"
#define NGM_COW_COOKIE          1018303300
#define NGM_COW_MOO             1

/* MALLOC define */
#ifdef NG_SEPARATE_MALLOC
MALLOC_DEFINE(M_NETGRAPH_COW, "cow", "Netgraph spherical cow");
#else
#define M_NETGRAPH_COW M_NETGRAPH
#endif /* NG_SEPARATE_MALLOC */

/* Netgraph node methods */
static ng_constructor_t ng_cow_constructor;
static ng_rcvmsg_t      ng_cow_rcvmsg;
static ng_shutdown_t    ng_cow_shutdown;
static ng_newhook_t     ng_cow_newhook;
static ng_connect_t     ng_cow_connect;
static ng_rcvdata_t     ng_cow_rcvdata;
static ng_disconnect_t  ng_cow_disconnect;
static int              ng_cow_modevent __P((module_t, int, void *));

/* Netgraph node command list */
static const struct ng_cmdlist  ng_cow_cmdlist[] = {
{
        NGM_COW_COOKIE,
        NGM_COW_MOO,
        "moo",
        NULL,
        NULL
},
{ 0, }
};

/* Netgraph type descriptor */
static struct ng_type   typestruct = {
        NG_ABI_VERSION,
        NG_COW_NODE_TYPE,       /* typename */
        ng_cow_modevent,        /* modevent */
        ng_cow_constructor,     /* constructor */
        ng_cow_rcvmsg,          /* control message */
        ng_cow_shutdown,        /* destructor */
        ng_cow_newhook,         /* new hook */
        NULL,                   /* find hook */
        ng_cow_connect,         /* connect hook */
        ng_cow_rcvdata,         /* data */
        ng_cow_disconnect,      /* disconnect hook */
        ng_cow_cmdlist          /* node command list */
};
NETGRAPH_INIT(cow, &typestruct);
MODULE_VERSION(ng_cow, 1);

static int              ng_cow_moo      __P((void));
static struct mbuf *    ng_cow_prepend  __P((struct mbuf *, int));

/*****************************************************************************
 *****************************************************************************
 **                        Netgraph node interface
 *****************************************************************************
 *****************************************************************************/

static node_p   the_node = NULL;

/*
 * Handle loading and unloading for this node type
 */

static int
ng_cow_modevent(mod, event, data)
        module_t         mod;
        int              event;
        void            *data;
{
        int             error = 0;

        switch (event) {
        case MOD_LOAD:
                error = ng_make_node_common(&typestruct, &the_node);
                if (error != 0)
                        break;

                error = ng_name_node(the_node, NG_COW_NODE_TYPE);
                if (error != 0) {
                        NG_NODE_UNREF(the_node);
                        the_node = NULL;
                        break;
                }
                break;

        case MOD_UNLOAD:
                error = EBUSY;
                break;

        default:
                error = EOPNOTSUPP;
                break;
        }

        return (error);
} /* ng_cow_modevent */

/*
 * Only one node is allowed and it is created when module is loaded
 */

static int
ng_cow_constructor(node)
        node_p  node;
{
        return (EINVAL);
} /* ng_cow_constructor */

/*
 * We do not allow any hook to be connected to the node.
 */

static int
ng_cow_newhook(node, hook, name)
        node_p           node;
        hook_p           hook;
        char const      *name;
{
        return (EINVAL);
} /* ng_cow_newhook */

/* 
 * Just say NO!
 */

static int
ng_cow_connect(hook)
        hook_p  hook;
{
        return (EINVAL);
} /* ng_cow_connect */

/*
 * Hook disconnection
 */

static int
ng_cow_disconnect(hook)
        hook_p  hook;
{
        return (0);
} /* ng_cow_disconnect */

/*
 * Do local shutdown processing
 */

static int
ng_cow_shutdown(node)
        node_p  node;
{
        if (ng_make_node_common(&typestruct, &the_node) != 0) {
                the_node = NULL;
                goto out;
        }

        if (ng_name_node(the_node, NG_COW_NODE_TYPE) != 0) {
                NG_NODE_UNREF(the_node);
                the_node = NULL;
        }
out:
        return (0);
} /* ng_cow_shutdown */

/*
 * Process incoming messages 
 */

static int
ng_cow_rcvmsg(node, item, hook)
        node_p  node;
        item_p  item;
        hook_p  hook;
{
        struct ng_mesg  *msg = NULL;
        int              error = 0;

        /* Detach message */
        NGI_GET_MSG(item, msg);

        /* Process message */
        switch (msg->header.typecookie) {
        case NGM_COW_COOKIE:
                switch (msg->header.cmd) {
                case NGM_COW_MOO:
                        error = ng_cow_moo();
                        break;

                default:
                        error = EINVAL;
                        break;
                }
                break;

        default:
                error = EINVAL;
                break;
        }

        NG_FREE_MSG(msg);

        return (error);
} /* ng_cow_rcvmsg */

/*
 * Receive data on a hook
 */

static int
ng_cow_rcvdata(hook, item)
        hook_p  hook;
        item_p  item;
{
        NG_FREE_ITEM(item);
        return (0);
} /* ng_cow_rcvdata */

/*
 * MOO 
 */

static int
ng_cow_moo(void)
{
#define DATA_SIZE       4100
#define CHUNK_SIZE      128

        struct mbuf     *m0 = NULL, *m = NULL, *first = NULL, *last = NULL;
        char             data[DATA_SIZE];
        int              error = 0;

        bzero(data, sizeof(data));
        MGETHDR(m0, M_DONTWAIT, MT_DATA);
        if (m0 == NULL)
                return (ENOBUFS);

        /* Copy data into mbuf starting at +4 bytes */
        m0->m_pkthdr.len = m0->m_len = 4;
        m_copyback(m0, m0->m_len, sizeof(data), data);

        /* Prepend mbuf with 4 bytes */
        m0 = ng_cow_prepend(m0, 4);
        if (m0 == NULL)
                return (ENOBUFS);

        /* Split result mbuf into chunks and link then via m_nextpkt */
        while (m0 != NULL) {
                int     len = m0->m_pkthdr.len;

                if (len > CHUNK_SIZE) {
                        m = m_split(m0, CHUNK_SIZE, M_DONTWAIT);
                        if (m == NULL) {
                                error = ENOBUFS;
                                break;
                        }
                }

                /* Prepend chunk with another 4 bytes */
                m0 = ng_cow_prepend(m0, 4);
                if (m0 == NULL) {
                        error = ENOBUFS;
                        break;
                }

                /* Add chunk to the list */
                m0->m_nextpkt = NULL;
                if (last == NULL)
                        first = last = m0;
                else {
                        last->m_nextpkt = m0;
                        last = m0;
                }

                m0 = m;
                m = NULL;
        }

        NG_FREE_M(m0);
        NG_FREE_M(m);

        while (first != NULL) {
                m = first->m_nextpkt;
                m_freem(first);
                first = m;
        }

        return (error);
} /* ng_cow_moo */

/*
 * prepend mbuf with size bytes
 */

static struct mbuf *
ng_cow_prepend(m, size)
        struct mbuf     *m;
        int              size;
{
        M_PREPEND(m, size, M_DONTWAIT);
        if (m == NULL || (m->m_len < size && (m = m_pullup(m, size)) == NULL))
                return (NULL);

        return (m);
} /* ng_cow_prepend */


CFLAGS+=        -g 
KMOD=           ng_cow
SRCS=           ng_cow.c
NOMAN=

.include <bsd.kmod.mk>
--- uipc_mbuf.c.orig    Mon Apr  8 14:40:23 2002
+++ uipc_mbuf.c Mon Apr  8 14:40:43 2002
@@ -584,6 +584,7 @@
                if (remain > MHLEN) {
                        /* m can't be the lead packet */
                        MH_ALIGN(n, 0);
+                       n->m_len = 0;
                        n->m_next = m_split(m, len, wait);
                        if (n->m_next == NULL) {
                                (void) m_free(n);
FreeBSD beetle 5.0-CURRENT FreeBSD 5.0-CURRENT #20: Mon Apr  8 14:45:30 PDT 2002     
max@beetle:/usr/src/sys/i386/compile/BEETLE  i386

Fatal double fault:
eip = 0xc01bb5b4
esp = 0xc9ffc000
ebp = 0xc9ffc00c
panic: double fault
Copyright (c) 1992-2002 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD 5.0-CURRENT #20: Mon Apr  8 14:45:30 PDT 2002
    max@beetle:/usr/src/sys/i386/compile/BEETLE
Preloaded elf kernel "/boot/kernel/kernel" at 0xc03ba000.
Preloaded elf module "/boot/kernel/nmdm.ko" at 0xc03ba0a8.
Timecounter "i8254"  frequency 1193182 Hz
Timecounter "TSC"  frequency 597789434 Hz
CPU: Pentium III/Pentium III Xeon/Celeron (597.79-MHz 686-class CPU)
  Origin = "GenuineIntel"  Id = 0x681  Stepping = 1
  
Features=0x383f9ff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE>
real memory  = 134086656 (130944K bytes)
avail memory = 126636032 (123668K bytes)
Pentium Pro MTRR support enabled
Using $PIR table, 10 entries at 0xc00f0130
npx0: <math processor> on motherboard
npx0: INT 16 interface
pcib0: <Intel 82443BX (440 BX) host to PCI bridge> at pcibus 0 on motherboard
pci0: <PCI bus> on pcib0
pcib1: <PCI-PCI bridge> at device 1.0 on pci0
pci1: <PCI bus> on pcib1
pci1: <display, VGA> at device 0.0 (no driver attached)
isab0: <PCI-ISA bridge> at device 3.0 on pci0
isa0: <ISA bus> on isab0
isab1: <PCI-ISA bridge> at device 5.0 on pci0
atapci0: <Intel PIIX4 ATA33 controller> port 0xfff0-0xffff at device 5.1 on pci0
ata0: at 0x1f0 irq 14 on atapci0
ata1: at 0x170 irq 15 on atapci0
uhci0: <Intel 82371AB/EB (PIIX4) USB controller> port 0xff80-0xff9f irq 11 at device 
5.2 on pci0
usb0: <Intel 82371AB/EB (PIIX4) USB controller> on uhci0
usb0: USB revision 1.0
uhub0: Intel UHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 2 ports with 2 removable, self powered
uhub1: Texas Instruments UT-USB41 hub, class 9/0, rev 1.00/1.00, addr 2
uhub1: 4 ports with 4 removable, self powered
pci0: <bridge, PCI-unknown> at device 5.3 (no driver attached)
pci0: <unknown> at device 9.0 (no driver attached)
pcm0: <Yamaha DS-1E (YMF744)> port 0xfefc-0xfeff,0xff00-0xff3f mem 
0xefff8000-0xefffffff irq 11 at device 12.0 on pci0
pcm0: ac97 codec invalid or not present (id == 0)
xl0: <3Com 3c905C-TX Fast Etherlink XL> port 0xfd80-0xfdff mem 0xefff7f80-0xefff7fff 
irq 11 at device 15.0 on pci0
xl0: Ethernet address: 00:00:39:8c:1e:26
miibus0: <MII bus> on xl0
xlphy0: <3c905C 10/100 internal PHY> on miibus0
xlphy0:  10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
orm0: <Option ROM> at iomem 0xc0000-0xcbfff on isa0
atkbdc0: <Keyboard controller (i8042)> at port 0x64,0x60 on isa0
atkbd0: <AT Keyboard> flags 0x1 irq 1 on atkbdc0
kbd0 at atkbd0
psm0: <PS/2 Mouse> irq 12 on atkbdc0
psm0: model MouseMan+, device ID 0
fdc0: <enhanced floppy controller (i82077, NE72065 or clone)> at port 
0x3f7,0x3f0-0x3f5 irq 6 drq 2 on isa0
pcic0: <Intel i82365SL-A/B> at port 0x3e0 iomem 0xd0000 on isa0
pcic0: Polling mode
pccard0: <PC Card bus (classic)> on pcic0
pccard1: <PC Card bus (classic)> on pcic0
pmtimer0 on isa0
sc0: <System console> at flags 0x100 on isa0
sc0: VGA <16 virtual consoles, flags=0x300>
sio0 at port 0x3f8-0x3ff irq 4 flags 0x10 on isa0
sio0: type 16550A
vga0: <Generic ISA VGA> at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0
unknown: <PNP0303> can't assign resources (port)
unknown: <PNP0f13> can't assign resources (irq)
unknown: <PNP0700> can't assign resources (port)
unknown: <PNP0501> can't assign resources (port)
IP packet filtering initialized, divert enabled, rule-based forwarding disabled, 
default to deny, logging limited to 100 packets/entry by default
pccard: card inserted, slot 0
pccard: card inserted, slot 1
ata1-slave: timeout waiting for interrupt
ata1-slave: ATAPI identify failed
ad0: 11513MB <IBM-DARA-212000> [23392/16/63] at ata0-master UDMA33
acd0: DVD-ROM <TOSHIBA DVD-ROM SD-C2302> at ata1-master PIO4
Mounting root from ufs:/dev/ad0s2a
WARNING: / was not properly dismounted
pccard: card removed, slot 0
pccard: card removed, slot 1
/dev/vmmon: Module vmmon: registered with major=200 minor=0 tag=$Name: build-570 $
/dev/vmmon: Module vmmon: initialized
WARNING: driver ptc should register devices with make_dev() (dev_t = "#ptc/0")

Reply via email to