lkml.org 
[lkml]   [2000]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH] lock troubles in pre6-2
    Here is a more complete listing of the issues found by a compiler-based
    checker after being filtered by me. The checker essentially checks that
    spin locks, interrupts, and bh's are paired up in functions, warning when
    the function can exit holding a lock, with interrupts disabled, or while
    bh's are disabled. It also tries to check for double locks/unlocks within
    the same function, and also restoring of flags not saved within the same
    function.

    I had to filter out ~250 false positives, the ones here are ones I've
    looked at at least briefly so there should be at least a few bugs :)

    Issues to be aware of:

    1. The context given for each potential bug is incomplete; it's necessary
    to consult the source.

    2. The version we checked is 2.3.99-? -- I'm not sure exactly which one
    but I can verify if needed.

    3. Some of the "bugs" are at most poor style, and there are probably false
    positives. The checker isn't global so it knows nothing about what goes
    on in function calls. It may be made global at some point (suggestions
    on how to do this effectively are welcome).

    4. If you can verify any of these, please cc mc@cs.stanford.edu.

    -Andy

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/atm/iphase.c:1691:tx_dle_intr: ERROR:LCK:HOLD: leaving function holding lock `(::tx_dle_intr (::atm_dev *)::iadev + 92)'
    BUG:DD:ECOND:

    static void tx_dle_intr(struct atm_dev *dev)
    {
    unsigned long flags;
    ...
    ==> Lock here
    spin_lock_irqsave(&iadev->tx_lock, flags);
    while (dle != cur_dle)
    {
    vcc = ATM_SKB(skb)->vcc;
    if (!vcc) {
    printk("tx_dle_intr: vcc is null\n");
    dev_kfree_skb_any(skb);
    ==> forgot to unlock
    return;
    }
    iavcc = INPH_IA_VCC(vcc);
    if (!iavcc) {
    printk("tx_dle_intr: iavcc is null\n");
    dev_kfree_skb_any(skb);
    ==> forgot to unlock
    return;
    }
    spin_unlock_irqrestore(&iadev->tx_lock, flags);
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/char/cyclades.c:1165:cyy_interrupt: ERROR:LCK:2L: relocking lock

    BUG:DD:ECOND

    static void
    cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    do{
    had_work = 0;
    for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
    while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) {
    if (status & CySRReceive) { /* reception interrupt */
    ==> Locking here
    spin_lock(&cinfo->card_lock);
    if(info->tty == 0){
    ...
    }else{
    if ( j == CyIVRRxEx ) { /* exception */
    if(data & info->ignore_status_mask){
    info->icount.rx++;
    ==> Forgot to unlock here
    continue;
    }
    if (status & CySRTransmit) { /* transmission interrupt */
    spin_lock(&cinfo->card_lock);
    ...
    spin_unlock(&cinfo->card_lock);
    }

    if (status & CySRModem) {
    spin_lock(&cinfo->card_lock);
    ...
    spin_unlock(&cinfo->card_lock);
    }
    }
    }
    } while(had_work);

    spin_lock(&cinfo->card_lock);
    cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<<index), 0);
    /* Cy_ClrIntr is 0x1800 */
    spin_unlock(&cinfo->card_lock);
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/char/n_r3964.c:990:add_msg: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
    int error_code, struct r3964_block_header *pBlock)
    {
    if(pClient->msg_count<R3964_MAX_MSG_COUNT-1)
    {
    ==> Disable interrupts
    save_flags(flags);
    cli();

    pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
    TRACE_M("add_msg - kmalloc %x",(int)pMsg);
    if(pMsg==NULL)
    ==> Return without restoring flags?
    return;
    ...
    restore_flags(flags);
    }
    else
    {
    ...
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/char/saa7110.c:76:saa7110_write_block: ERROR:LCK:HOLD: leaving function holding lock `(::saa7110_write_block (::saa7110 *, const unsigned char *, unsigned int)::decoder->::saa7110::bus + 40)'

    BUG:DD:ECOND

    static
    int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
    {
    unsigned subaddr = *data;

    ==> Calls spin_lock_irqsave
    LOCK_I2C_BUS(decoder->bus);
    i2c_start(decoder->bus);
    i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
    while (len-- > 0) {
    if (i2c_sendbyte(decoder->bus,*data,0)) {
    i2c_stop(decoder->bus);
    ==> Forgot to unlock
    return -EAGAIN;
    }
    decoder->reg[subaddr++] = *data++;
    }
    i2c_stop(decoder->bus);
    UNLOCK_I2C_BUS(decoder->bus);

    return 0;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/i2o/i2o_block.c:1412:i2ob_del_device: ERROR:LCK:HOLD: leaving function holding lock `&::io_request_lock'

    BUG:DD:ECOND

    void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
    {
    ==> Lock here
    spin_lock_irqsave(&io_request_lock, flags);

    if(unit >= MAX_I2OB<<4)
    {
    printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
    ==> Missing unlock
    return;
    }

    ...
    spin_unlock_irqrestore(&io_request_lock, flags);
    ...
    return;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/ide/ide-disk.c:697:set_nowerr: ERROR:FLAGS: restoring flags without saving them

    BUG:DD:FLAGARG should not pass flags as arguments?

    static int set_nowerr(ide_drive_t *drive, int arg)
    {
    unsigned long flags;

    if (ide_spin_wait_hwgroup(drive, &flags))
    return -EBUSY;
    drive->nowerr = arg;
    drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
    spin_unlock_irqrestore(&io_request_lock, flags);
    return 0;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/isdn/hisax/config.c:1063:checkcard: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    HISAX_INITFUNC(static int
    checkcard(int cardnr, char *id, int *busy_flag))
    {
    ==> save flags
    save_flags(flags);
    cli();
    ...
    if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
    printk(KERN_WARNING
    "HiSax: No memory for isac rcvbuf\n");
    ==> not restoring flags
    return (1);
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/isdn/isdn_net.h:174:isdn_net_get_locked_lp: ERROR:LCK:HOLD: leaving function holding lock `(::isdn_net_get_locked_lp (::isdn_net_dev *)::nd->::isdn_net_dev_s::queue + 304)'

    BUG:DD:ECOND

    static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
    {
    unsigned long flags;
    isdn_net_local *lp;

    ==> Save queue_lock
    spin_lock_irqsave(&nd->queue_lock, flags);
    lp = nd->queue; /* get lp on top of queue */
    spin_lock_bh(&nd->queue->xmit_lock);
    while (isdn_net_lp_busy(nd->queue)) {
    spin_unlock_bh(&nd->queue->xmit_lock);
    nd->queue = nd->queue->next;
    if (nd->queue == lp) /* not found -- should never happen */
    ==> Forgot to restore queue_lock
    return 0;
    spin_lock_bh(&nd->queue->xmit_lock);
    }
    lp = nd->queue;

    nd->queue = nd->queue->next;
    spin_unlock_irqrestore(&nd->queue_lock, flags);
    return lp;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/isdn/isdn_ppp.c:435:isdn_ppp_bind: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    int
    isdn_ppp_bind(isdn_net_local * lp)
    {
    save_flags(flags);
    cli();
    ...
    if (unit < 0) {
    printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
    return -1;
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/appletalk/cops.c:746:cops_rx: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    static void cops_rx(struct net_device *dev)
    {
    ==> Disable intr
    save_flags(flags);
    cli(); /* Disable interrupts. */

    if(lp->board==DAYNA)
    {
    outb(0, ioaddr); /* Send out Zero length. */
    outb(0, ioaddr);
    outb(DATA_READ, ioaddr); /* Send read command out. */

    /* Wait for DMA to turn around. */
    while(++boguscount<1000000)
    {
    if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)
    break;
    }

    if(boguscount==1000000)
    {
    printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);
    ==> Forgot to restore flags
    return;
    }
    }
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/de4x5.c:1618:de4x5_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::de4x5_interrupt (int, void *, ::pt_regs *)::lp + 524)'

    BUG:DD:ECOND

    static void
    de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    ==> Locking here
    spin_lock(&lp->lock);
    ==> Only disables a particular intr
    DISABLE_IRQs; /* Ensure non re-entrancy */

    for (limit=0; limit<8; limit++) {
    ...
    if (sts & STS_SE) { /* Bus Error */
    STOP_DE4X5;
    printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",
    dev->name, sts);
    ==> Not unlocking
    return;
    }
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/de4x5.c:5585:de4x5_ioctl: ERROR:LCK:HOLD: leaving function holding lock `(::de4x5_ioctl (::net_device *, ::ifreq *, int)::lp + 524)'

    BUG:DD:ECOND:SLEEP

    static int
    de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
    {

    switch(ioc->cmd) {
    ...
    case DE4X5_GET_STATS: /* Get the driver statistics */
    ioc->len = sizeof(lp->pktStats);
    ==> Lock here
    spin_lock_irqsave(&lp->lock, flags);
    ==> Not unlocking on error, calling copy_to_user
    if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT;
    spin_unlock_irqrestore(&lp->lock, flags);
    break;
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/hamradio/soundmodem/sm_wss.c:159:wss_set_codec_fmt: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    static int wss_set_codec_fmt(struct net_device *dev, struct sm_state *sm, unsigned char fmt,
    unsigned char fmt2, char fdx, char fullcalib)
    {
    unsigned long time;
    unsigned long flags;
    ==> Save flags, disable intr
    save_flags(flags);
    cli();
    /* Clock and data format register */
    write_codec(dev, 0x48, fmt);
    if (SCSTATE->crystal) {
    write_codec(dev, 0x5c, fmt2 & 0xf0);
    /* MCE and interface config reg */
    write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0));
    } else
    /* MCE and interface config reg */
    write_codec(dev, 0x49, fdx ? 0x8 : 0xc);
    outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */
    if (SCSTATE->crystal && !fullcalib)
    ==> Missing restore flags here
    return 0;
    /*
    * wait for ACI start
    */
    time = 1000;
    while (!(read_codec(dev, 0x0b) & 0x20))
    if (!(--time)) {
    printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n",
    sm_drvname);
    ==> Carefully restored here
    restore_flags(flags);
    return -1;
    }
    /*
    * wait for ACI end
    */
    sti();
    time = jiffies + HZ/4;
    while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0));
    ==> Carefully restored here
    restore_flags(flags);
    if ((signed)(jiffies - time) >= 0) {
    printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n",
    sm_drvname);
    return -1;
    }
    return 0;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/irda/irport.c:923:irport_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled

    Four bugs.

    BUG:DD:ECOND
    BUG:DD:ECOND
    BUG:DD:ECOND
    BUG:DD:ECOND

    static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
    {
    self = dev->priv;

    ASSERT(self != NULL, return -1;);

    IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);

    /* Disable interrupts & save flags */
    ==> Save here
    save_flags(flags);
    cli();

    switch (cmd) {
    case SIOCSBANDWIDTH: /* Set bandwidth */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_task_execute(self, __irport_change_speed, NULL, NULL,
    (void *) irq->ifr_baudrate);
    break;
    case SIOCSDONGLE: /* Set dongle */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    /* Initialize dongle */
    dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
    if (!dongle)
    break;

    dongle->set_mode = NULL;
    dongle->read = NULL;
    dongle->write = irport_raw_write;
    dongle->set_dtr_rts = irport_set_dtr_rts;

    self->dongle = dongle;

    /* Now initialize the dongle! */
    dongle->issue->open(dongle, &self->qos);

    /* Reset dongle */
    irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
    NULL);
    break;
    case SIOCSMEDIABUSY: /* Set media busy */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_device_set_media_busy(self->netdev, TRUE);
    break;
    case SIOCGRECEIVING: /* Check if we are receiving right now */
    irq->ifr_receiving = irport_is_receiving(self);
    break;
    case SIOCSDTRRTS:
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
    break;
    default:
    ret = -EOPNOTSUPP;
    }

    restore_flags(flags);

    return ret;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/irda/irtty.c:943:irtty_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled

    Similar to the above bugs.

    BUG:DD:ECOND
    BUG:DD:ECOND
    BUG:DD:ECOND
    BUG:DD:ECOND
    BUG:DD:ECOND

    static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
    {
    struct if_irda_req *irq = (struct if_irda_req *) rq;
    struct irtty_cb *self;
    dongle_t *dongle;
    unsigned long flags;
    int ret = 0;

    ASSERT(dev != NULL, return -1;);

    self = dev->priv;

    ASSERT(self != NULL, return -1;);
    ASSERT(self->magic == IRTTY_MAGIC, return -1;);

    IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);

    /* Disable interrupts & save flags */
    ==> Save flags, disable intr
    save_flags(flags);
    cli();

    switch (cmd) {
    case SIOCSBANDWIDTH: /* Set bandwidth */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_task_execute(self, irtty_change_speed, NULL, NULL,
    (void *) irq->ifr_baudrate);
    break;
    case SIOCSDONGLE: /* Set dongle */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    /* Initialize dongle */
    dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
    if (!dongle)
    break;

    dongle->set_mode = irtty_set_mode;
    dongle->read = irtty_raw_read;
    dongle->write = irtty_raw_write;
    dongle->set_dtr_rts = irtty_set_dtr_rts;

    self->dongle = dongle;

    /* Now initialize the dongle! */
    dongle->issue->open(dongle, &self->qos);

    /* Reset dongle */
    irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
    NULL);
    break;
    case SIOCSMEDIABUSY: /* Set media busy */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_device_set_media_busy(self->netdev, TRUE);
    break;
    case SIOCGRECEIVING: /* Check if we are receiving right now */
    irq->ifr_receiving = irtty_is_receiving(self);
    break;
    case SIOCSDTRRTS:
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
    break;
    case SIOCSMODE:
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irtty_set_mode(dev, irq->ifr_mode);
    break;
    default:
    ret = -EOPNOTSUPP;
    }

    restore_flags(flags);

    return ret;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/irda/nsc-ircc.c:1930:nsc_ircc_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled

    Similar to bugs above.
    BUG:DD:ECOND
    BUG:DD:ECOND

    static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
    {
    ...
    /* Disable interrupts & save flags */
    ==> Disable here
    save_flags(flags);
    cli();

    switch (cmd) {
    case SIOCSBANDWIDTH: /* Set bandwidth */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    nsc_ircc_change_speed(self, irq->ifr_baudrate);
    break;
    case SIOCSMEDIABUSY: /* Set media busy */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_device_set_media_busy(self->netdev, TRUE);
    break;
    case SIOCGRECEIVING: /* Check if we are receiving right now */
    irq->ifr_receiving = nsc_ircc_is_receiving(self);
    break;
    default:
    ret = -EOPNOTSUPP;
    }

    restore_flags(flags);

    return ret;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/irda/toshoboe.c:586:toshoboe_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled

    Similar to bugs above.

    BUG:DD:ECOND
    BUG:DD:ECOND

    static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
    {
    ...
    /* Disable interrupts & save flags */
    ==> Disable here
    save_flags(flags);
    cli();

    switch (cmd) {
    case SIOCSBANDWIDTH: /* Set bandwidth */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    /* toshoboe_setbaud(self, irq->ifr_baudrate); */
    /* Just change speed once - inserted by Paul Bristow */
    self->new_speed = irq->ifr_baudrate;
    break;
    case SIOCSMEDIABUSY: /* Set media busy */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_device_set_media_busy(self->netdev, TRUE);
    break;
    case SIOCGRECEIVING: /* Check if we are receiving right now */
    irq->ifr_receiving = 0; /* Can't tell */
    break;
    default:
    ret = -EOPNOTSUPP;
    }

    restore_flags(flags);

    return ret;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/irda/w83977af_ir.c:1315:w83977af_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled

    Similar to bugs above.

    BUG:DD:ECOND
    BUG:DD:ECOND

    static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
    {
    ...
    /* Disable interrupts & save flags */
    ==> Disable here
    save_flags(flags);
    cli();

    switch (cmd) {
    case SIOCSBANDWIDTH: /* Set bandwidth */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    w83977af_change_speed(self, irq->ifr_baudrate);
    break;
    case SIOCSMEDIABUSY: /* Set media busy */
    if (!capable(CAP_NET_ADMIN))
    ==> Missing restore
    return -EPERM;
    irda_device_set_media_busy(self->netdev, TRUE);
    break;
    case SIOCGRECEIVING: /* Check if we are receiving right now */
    irq->ifr_receiving = w83977af_is_receiving(self);
    break;
    default:
    ret = -EOPNOTSUPP;
    }

    restore_flags(flags);

    return ret;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/pcmcia/netwave_cs.c:1164:netwave_hw_xmit: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    static int netwave_hw_xmit(unsigned char* data, int len,
    struct net_device* dev) {
    /* Disable interrupts & save flags */
    ==> Disable here
    save_flags(flags);
    cli();

    /* Check if there are transmit buffers available */
    wait_WOC(iobase);
    if ((inb(iobase+NETWAVE_REG_ASR) & NETWAVE_ASR_TXBA) == 0) {
    /* No buffers available */
    printk(KERN_DEBUG "netwave_hw_xmit: %s - no xmit buffers available.\n",
    dev->name);
    ==> Missing restore
    return 1;
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/pcmcia/nmclan_cs.c:1126:mace_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::mace_interrupt (int, void *, ::pt_regs *)::lp + 568)'

    BUG:DD:ECOND

    static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    ...
    ==> Lock here
    spin_lock (&lp->lock);

    if (lp->tx_irq_disabled) {
    printk(
    (lp->tx_irq_disabled?
    KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
    "[isr=%02X, imr=%02X]\n":
    KERN_NOTICE "%s: Re-entering the interrupt handler "
    "[isr=%02X, imr=%02X]\n"),
    dev->name,
    inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
    inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)
    );
    /* WARNING: MACE_IR has been read! */
    ==> Missing unlock
    return;
    }

    if (!netif_device_present(dev)) {
    DEBUG(2, "%s: interrupt from dead card\n", dev->name);
    goto exception;
    }
    ...
    exception:
    spin_unlock (&lp->lock);
    } /* mace_interrupt */

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/pcmcia/smc91c92_cs.c:1499:smc_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::smc_interrupt (int, void *, ::pt_regs *)::smc + 720)'

    BUG:DD:ECOND

    static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    ==> Lock here
    spin_lock (&smc->lock);
    if ((saved_bank & 0xff00) != 0x3300) {
    /* The device does not exist -- the card could be off-line, or
    maybe it has been ejected. */
    ==> Goto irq_done below
    goto irq_done;
    }

    ==> Unlock here skipped!
    spin_unlock (&smc->lock);

    DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);

    ==> Error jumps to here
    irq_done:
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/pcmcia/wavelan_cs.c:2516:wavelan_get_wireless_stats: ERROR:LCK:HOLD: leaving function holding lock `::wavelan_get_wireless_stats (::device *)::lp'

    BUG:DD:ECOND

    static iw_stats *
    wavelan_get_wireless_stats(device * dev)
    {
    ioaddr_t base = dev->base_addr;
    net_local * lp = (net_local *) dev->priv;
    mmr_t m;
    iw_stats * wstats;
    unsigned long flags;

    /* Disable interrupts & save flags */
    ==> Lock here
    spin_lock_irqsave (&lp->lock, flags);

    ==> Too late to test lp == null!
    if(lp == (net_local *) NULL)
    ==> Impossible return
    return (iw_stats *) NULL;
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/pcmcia/xirc2ps_cs.c:1389:xirc2ps_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::xirc2ps_interrupt (int, void *, ::pt_regs *)::lp + 704)'

    BUG:DD

    static void
    xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    ==> Lock
    spin_lock (&lp->lock);
    if (!netif_device_present(dev))
    ==> Missing unlock
    return;
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/sk98lin/skge.c:2389:SkGeChangeMtu: ERROR:LCK:HOLD: leaving function holding lock `((::SkGeChangeMtu (::net_device *, int)::pAC + (+(::SkGeChangeMtu (::net_device *, int)::i * 88))) + 14336)'

    BUG:DD: counts as one bug b/c the checker only found a side-effect of the errors

    static int SkGeChangeMtu(struct net_device *dev, int NewMtu)
    {
    ...
    ==> Lock here, save flags
    spin_lock_irqsave(&pAC->SlowPathLock, Flags);
    SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
    SkEventDispatcher(pAC, pAC->IoBase);

    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
    ==> Bogus: Overwrites flags
    spin_lock_irqsave(
    &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
    }
    netif_stop_queue(pAC->dev);
    ...
    netif_start_queue(pAC->dev);
    for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
    ==> Bogus: leaves intr disabled
    spin_unlock_irqrestore(
    &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
    }

    /* enable Interrupts */
    SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
    SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);

    SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
    SkEventDispatcher(pAC, pAC->IoBase);

    ==> Bogus: flags already mucked
    spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);

    return 0;
    } /* SkGeChangeMtu */

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/slip.c:1249:sl_ioctl: ERROR:BH:DIS: leaving function with bottom half disabled

    BUG:DD:ECOND
    BUG:DD:ECOND

    There are more bugs in this function, counted below.

    static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
    {
    struct slip *sl = (struct slip*)(dev->priv);

    if (sl == NULL) /* Allocation failed ?? */
    return -ENODEV;
    ==> Lock here
    spin_lock_bh(&sl->lock);
    ...
    switch(cmd){
    case SIOCSKEEPALIVE:
    /* max for unchar */
    if (((unsigned int)((unsigned long)rq->ifr_data)) > 255)
    ==> Not unlocking
    return -EINVAL;
    sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
    if (sl->keepalive != 0) {
    sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
    mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
    set_bit(SLF_KEEPTEST, &sl->flags);
    } else {
    del_timer(&sl->keepalive_timer);
    }
    spin_unlock_bh(&sl->lock);
    break;

    case SIOCGKEEPALIVE:
    rq->ifr_data=(caddr_t)((unsigned long)sl->keepalive);
    break;

    case SIOCSOUTFILL:
    if (((unsigned)((unsigned long)rq->ifr_data)) > 255) /* max for unchar */
    ==> Not unlocking
    return -EINVAL;
    if ((sl->outfill = (unchar)((unsigned long) rq->ifr_data)) != 0){
    mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
    set_bit(SLF_OUTWAIT, &sl->flags);
    } else {
    del_timer (&sl->outfill_timer);
    }
    break;

    case SIOCGOUTFILL:
    rq->ifr_data=(caddr_t)((unsigned long)sl->outfill);
    break;

    case SIOCSLEASE:
    /* Resolve race condition, when ioctl'ing hanged up
    and opened by another process device.
    */
    if (sl->tty != current->tty && sl->pid != current->pid) {
    spin_unlock_bh(&sl->lock);
    return -EPERM;
    }
    sl->leased = 0;
    if ((unsigned long)rq->ifr_data)
    sl->leased = 1;
    break;

    case SIOCGLEASE:
    rq->ifr_data=(caddr_t)((unsigned long)sl->leased);
    };
    spin_unlock_bh(&sl->lock);
    return 0;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/slip.c:1313:sl_ioctl: ERROR:LCK:2U: double unlock

    Same function as above, different bug:
    BUG:DD

    static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
    {
    struct slip *sl = (struct slip*)(dev->priv);

    ==> Lock here
    spin_lock_bh(&sl->lock);

    switch(cmd){
    case SIOCSKEEPALIVE:
    /* max for unchar */
    if (((unsigned int)((unsigned long)rq->ifr_data)) > 255)
    return -EINVAL;
    sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
    if (sl->keepalive != 0) {
    sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
    mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
    set_bit(SLF_KEEPTEST, &sl->flags);
    } else {
    del_timer(&sl->keepalive_timer);
    }
    ==> Unlock here
    spin_unlock_bh(&sl->lock);
    break;
    ... many buggy cases ...
    }
    ...
    ==> Double unlock here
    spin_unlock_bh(&sl->lock);
    return 0;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/tokenring/smctr.c:3578:smctr_open_tr: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND: should these count as separate bugs?
    BUG:DD:ECOND: should these count as separate bugs?
    BUG:DD:ECOND: should these count as separate bugs?
    BUG:DD:ECOND: should these count as separate bugs?

    /* Interrupt driven open of Token card. */
    static int smctr_open_tr(struct net_device *dev)
    {
    ==> Disable intr
    save_flags(flags);
    cli();

    smctr_set_page(dev, (__u8 *)tp->ram_access);

    if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
    ==> Missing restore
    return (err);

    if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
    ==> Missing restore
    return (err);

    if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
    ==> Missing restore
    return (err);

    if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
    ==> Missing restore
    return (err);
    ...
    restore_flags(flags);

    return (err);
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/tokenring/smctr.c:4596:smctr_rx_frame: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD: suspicious at the very least

    static int smctr_rx_frame(struct net_device *dev)
    {
    struct net_local *tp = (struct net_local *)dev->priv;
    __u16 queue, status, rx_size, err = 0;
    __u8 *pbuff;

    if(smctr_debug > 10)
    printk("%s: smctr_rx_frame\n", dev->name);

    ==> cli
    cli();
    queue = tp->receive_queue_number;

    while((status = tp->rx_fcb_curr[queue]->frame_status) != SUCCESS)
    {
    err = HARDWARE_FAILED;

    if(((status & 0x007f) == 0)
    || ((tp->receive_mask & ACCEPT_ERR_PACKETS) != 0))
    {
    /* frame length less the CRC (4 bytes) + FS (1 byte) */
    rx_size = tp->rx_fcb_curr[queue]->frame_length - 5;

    pbuff = smctr_get_rx_pointer(dev, queue);

    smctr_set_page(dev, pbuff);
    smctr_disable_16bit(dev);

    /* pbuff points to addr within one page */
    pbuff = (__u8 *)PAGE_POINTER(pbuff);

    if(queue == NON_MAC_QUEUE)
    {
    struct sk_buff *skb;

    ==> An unrelated bug: skb may be null, accessed in skb_put
    skb = dev_alloc_skb(rx_size);
    skb_put(skb, rx_size);

    memcpy(skb->data, pbuff, rx_size);
    ==> Enable intr... but then this loop executed with intr's enabled
    sti();

    /* Update Counters */
    tp->MacStat.rx_packets++;
    tp->MacStat.rx_bytes += skb->len;

    /* Kick the packet on up. */
    skb->dev = dev;
    skb->protocol = tr_type_trans(skb, dev);
    netif_rx(skb);
    }
    else
    smctr_process_rx_packet((MAC_HEADER *)pbuff,
    rx_size, dev, status);
    }

    smctr_enable_16bit(dev);
    smctr_set_page(dev, (__u8 *)tp->ram_access);
    smctr_update_rx_chain(dev, queue);

    if(err != SUCCESS)
    break;
    }
    ==> Not restoring interrupt status...
    return (err);
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:479:MIXCOM_open: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    static int MIXCOM_open(struct net_device *dev)
    {
    ...
    ==> Disable intr
    save_flags(flags); cli();

    if(hw->channel==1) {
    request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name);
    }

    if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) {
    if (request_irq(dev->irq, MIXCOM_interrupt, 0,
    dev->name, (void *)dev)) {
    printk(KERN_ERR "MIXCOM: unable to obtain irq %d\n", dev->irq);
    ==> Missing restore
    return -EAGAIN;
    }
    ch->init_status|=IRQ_ALLOCATED;
    request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name);
    mixcom_board_on(dev);
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/wan/lmc/lmc_main.c:152:lmc_ioctl: ERROR:LCK:HOLD: leaving function holding lock `(::lmc_ioctl (::net_device *, ::ifreq *, int)::sc + 1872)'

    This bug occurs in two macros, though the macros appear many times
    BUG:DD:ECOND
    BUG:DD:ECOND

    int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
    {
    ...
    ==> Lock, disable intr
    spin_lock_irqsave(&sc->lmc_lock, flags);
    switch (cmd) {
    case LMCIOCGINFO: /*fold01*/
    ==> This macro causes 2 bugs: copy_to_user and returns if error
    LMC_COPY_TO_USER(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t));
    ret = 0;
    break;

    }
    ==> The broken macro (and also LMC_COPY_FROM_USER) is used in 9 other cases
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/wan/lmc/lmc_main.c:650:lmc_watchdog: ERROR:LCK:HOLD: leaving function holding lock `(::lmc_watchdog (long unsigned int)::sc + 1872)'

    BUG:DD:ECOND

    static void lmc_watchdog (unsigned long data) /*fold00*/
    {
    ...
    ==> Lock
    spin_lock_irqsave(&sc->lmc_lock, flags);

    if(sc->check != 0xBEAFCAFE){
    printk("LMC: Corrupt net_device stuct, breaking out\n");
    ==> Not unlocking
    return;
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/net/wavelan.c:3662:wavelan_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::wavelan_interrupt (int, void *, ::pt_regs *)::lp + 8)'

    BUG:DD:ECOND

    static void wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    ...
    ==> Lock
    spin_lock(&lp->spinlock);
    ...
    /* Check if not controller interrupt */
    if ((hasr & HASR_82586_INTR) == 0) {
    #ifdef DEBUG_INTERRUPT_ERROR
    printk(KERN_INFO
    "%s: wavelan_interrupt(): interrupt not coming from i82586\n",
    dev->name);
    #endif
    ==> Missing unlock
    return;
    }
    ...
    /* Release spinlock here so that wv_hw_reset() can grab it */
    spin_unlock (&lp->spinlock);

    }
    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/53c7,8xx.c:4154:process_issue_queue: ERROR:FLAGS: restoring flags without saving them

    BUG:DD:FLAGARG passing flags in as argument
    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/aic7xxx.c:7021:do_aic7xxx_isr: ERROR:LCK:HOLD: leaving function holding lock `&::io_request_lock'

    BUG:DD

    /*+F*************************************************************************
    * Function:
    * do_aic7xxx_isr
    *
    * Description:
    * This is a gross hack to solve a problem in linux kernels 2.1.85 and
    * above. Please, children, do not try this at home, and if you ever see
    * anything like it, please inform the Gross Hack Police immediately
    *-F*************************************************************************/
    static void
    do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
    {
    unsigned long cpu_flags;
    struct aic7xxx_host *p;

    p = (struct aic7xxx_host *)dev_id;
    if(!p)
    return;
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
    ==> Lock
    spin_lock_irqsave(&io_request_lock, cpu_flags);
    if(test_and_set_bit(AHC_IN_ISR_BIT, (void *)&p->flags))
    {
    ==> Missing unlock
    return;
    }
    do
    {
    aic7xxx_isr(irq, dev_id, regs);
    } while ( (aic_inb(p, INTSTAT) & INT_PEND) );
    aic7xxx_done_cmds_complete(p);
    aic7xxx_run_waiting_queues(p);
    clear_bit(AHC_IN_ISR_BIT, (void *)&p->flags);
    spin_unlock_irqrestore(&io_request_lock, cpu_flags);
    #else
    if(set_bit(AHC_IN_ISR_BIT, (int *)&p->flags))
    {
    return;
    }
    DRIVER_LOCK
    do
    {
    aic7xxx_isr(irq, dev_id, regs);
    } while ( (aic_inb(p, INTSTAT) & INT_PEND) );
    DRIVER_UNLOCK
    aic7xxx_done_cmds_complete(p);
    aic7xxx_run_waiting_queues(p);
    clear_bit(AHC_IN_ISR_BIT, (int *)&p->flags);
    #endif
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/eata_dma.c:454:eata_queue: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *))
    {
    ...
    ==> Disable intr
    save_flags(flags);
    cli();
    ...
    if (cmd->cmnd[0] == REQUEST_SENSE && cmd->sense_buffer[0] != 0) {
    DBG(DBG_REQSENSE, printk(KERN_DEBUG "Tried to REQUEST SENSE\n"));
    cmd->result = DID_OK << 16;
    done(cmd);
    ==> Missing restore
    return(0);
    }
    ...
    if (x >= sh->can_queue) {
    cmd->result = DID_BUS_BUSY << 16;
    DBG(DBG_QUEUE && DBG_ABNORM,
    printk(KERN_CRIT "eata_queue pid %ld, HBA QUEUE FULL..., "
    "returning DID_BUS_BUSY\n", cmd->pid));
    done(cmd);
    ==> Did the Right Thing here
    restore_flags(flags);
    return(0);
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/qla1280.c:1506:qla1280_intr_handler: ERROR:LCK:HOLD: leaving function holding lock `&::io_request_lock'

    BUG:DD

    void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
    {
    ...
    ==> Lock, disable intr here
    spin_lock_irqsave(&io_request_lock, cpu_flags);
    if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags))
    {
    COMTRACE('X')
    ==> Missing unlock
    return;
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/sg.c:2514:sg_proc_debug_info: ERROR:LCK:HOLD: leaving function holding lock `&::sg_dev_arr_lock'

    BUG:DD

    static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
    off_t offset, int size)
    {
    Sg_device * sdp;
    const sg_io_hdr_t * hp;
    int j, max_dev;

    if (NULL == sg_dev_arr) {
    PRINT_PROC("sg_dev_arr NULL, driver not initialized\n");
    return 1;
    }
    ==> Lock here
    read_lock(&sg_dev_arr_lock);
    max_dev = sg_last_dev();
    PRINT_PROC("dev_max(currently)=%d max_active_device=%d (origin 1)\n",
    sg_template.dev_max, max_dev);
    PRINT_PROC(" scsi_dma_free_sectors=%u sg_pool_secs_aval=%d "
    "def_reserved_size=%d\n",
    scsi_dma_free_sectors, sg_pool_secs_avail, sg_big_buff);
    for (j = 0; j < max_dev; ++j) {
    if ((sdp = sg_dev_arr[j])) {
    Sg_fd * fp;
    Sg_request * srp;
    struct scsi_device * scsidp;
    int dev, k, blen, usg;

    if (! (scsidp = sdp->device)) {
    PRINT_PROC("device %d detached ??\n", j);
    continue;
    }
    dev = MINOR(sdp->i_rdev);

    if ((fp = sdp->headfp)) {
    PRINT_PROC(" >>> device=%d(sg%d) ", dev, dev);
    PRINT_PROC("scsi%d chan=%d id=%d lun=%d em=%d sg_tablesize=%d"
    " excl=%d\n", scsidp->host->host_no, scsidp->channel,
    scsidp->id, scsidp->lun, scsidp->host->hostt->emulated,
    sdp->sg_tablesize, sdp->exclude);
    }
    for (k = 1; fp; fp = fp->nextfp, ++k) {
    PRINT_PROC(" FD(%d): timeout=%d bufflen=%d "
    "(res)sgat=%d low_dma=%d\n",
    k, fp->timeout, fp->reserve.bufflen,
    (int)fp->reserve.k_use_sg, (int)fp->low_dma);
    PRINT_PROC(" cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n",
    (int)fp->cmd_q, (int)fp->force_packid,
    (int)fp->keep_orphan, (int)fp->closed);
    srp = fp->headrp;
    if (NULL == srp)
    PRINT_PROC(" No requests active\n");
    while (srp) {
    hp = &srp->header;
    /* stop indenting so far ... */
    PRINT_PROC(srp->res_used ? " rb>> " :
    ((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " "));
    blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen;
    usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg;
    PRINT_PROC(srp->done ? "rcv: id=%d" : (srp->my_cmdp ? "act: id=%d" :
    "prior: id=%d"), srp->header.pack_id);
    PRINT_PROC(" blen=%d", blen);
    if (srp->done)
    PRINT_PROC(" dur=%d", sg_jif_to_ms(hp->duration));
    else
    PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ?
    sg_jif_to_ms(fp->timeout) : hp->timeout),
    sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
    PRINT_PROC(" sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode);
    srp = srp->nextrp;
    /* reset indenting */
    }
    }
    }
    }
    ==> Unlock here
    read_unlock(&sg_dev_arr_lock);
    return 1;
    }

    Didn't see the bug? Look at this:

    #define PRINT_PROC(fmt,args...) \
    do { \
    *len += sprintf(buffer + *len, fmt, ##args); \
    if (*begin + *len > offset + size) \
    ==> Here we go
    return 0; \
    if (*begin + *len < offset) { \
    *begin += *len; \
    *len = 0; \
    } \
    } while(0)


    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/sg.c:2594:sg_proc_dev_info: ERROR:LCK:HOLD: leaving function holding lock `&::sg_dev_arr_lock'

    BUG:DD

    static int sg_proc_dev_info(char * buffer, int * len, off_t * begin,
    off_t offset, int size)
    {
    Sg_device * sdp;
    int j, max_dev;
    struct scsi_device * scsidp;

    ==> Lock here
    read_lock(&sg_dev_arr_lock);
    max_dev = sg_last_dev();
    for (j = 0; j < max_dev; ++j) {
    sdp = sg_dev_arr[j];
    if (sdp && (scsidp = sdp->device))
    ==> See above macro
    PRINT_PROC("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
    scsidp->host->host_no, scsidp->channel, scsidp->id,
    scsidp->lun, (int)scsidp->type, (int)scsidp->disconnect,
    (int)scsidp->queue_depth, (int)scsidp->tagged_queue);
    else
    ==> See above macro
    PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
    }
    read_unlock(&sg_dev_arr_lock);
    return 1;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/sg.c:2632:sg_proc_devstrs_info: ERROR:LCK:HOLD: leaving function holding lock `&::sg_dev_arr_lock'

    BUG:DD

    static int sg_proc_devstrs_info(char * buffer, int * len, off_t * begin,
    off_t offset, int size)
    {
    Sg_device * sdp;
    int j, max_dev;
    struct scsi_device * scsidp;

    ==> Lock here
    read_lock(&sg_dev_arr_lock);
    max_dev = sg_last_dev();
    for (j = 0; j < max_dev; ++j) {
    sdp = sg_dev_arr[j];
    if (sdp && (scsidp = sdp->device))
    ==> See above macro
    PRINT_PROC("%8.8s\t%16.16s\t%4.4s\n",
    scsidp->vendor, scsidp->model, scsidp->rev);
    else
    ==> See above macro
    PRINT_PROC("<no active device>\n");
    }
    read_unlock(&sg_dev_arr_lock);
    return 1;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/scsi/sim710.c:1256:process_issue_queue: ERROR:FLAGS: restoring flags without saving them

    BUG:DD:FLAGARG flags used as argument...
    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/sound/ad1848.c:2724:ad1848_resume: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD:ECOND

    static int ad1848_resume(ad1848_info *devc)
    {
    ==> Disable intr
    save_flags(flags);
    cli();
    if (!devc->subtype) {
    ...
    if (bits == -1) {
    printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq);
    ==> Missing restore
    return -1;
    }
    ...
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/sound/gus_wave.c:637:start_release: ERROR:FLAGS: restoring flags without saving them

    BUG:DD:FLAGARG: flags passed as argument
    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/sound/i810_audio.c:919:i810_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::i810_interrupt (int, void *, ::pt_regs *)::card + 824)'

    BUG:DD

    static void i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    struct i810_card *card = (struct i810_card *)dev_id;
    u32 status;

    ==> Lock
    spin_lock(&card->lock);

    status = inl(card->iobase + GLOB_STA);
    if(!(status & INT_MASK))
    ==> Missing unlock
    return; /* not for us */

    // printk("Interrupt %X: ", status);
    if(status & (INT_PO|INT_PI|INT_MC))
    i810_channel_interrupt(card);

    /* clear 'em */
    outl(status & INT_MASK, card->iobase + GLOB_STA);
    spin_unlock(&card->lock);
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/sound/sscape.c:938:sscape_pnp_upload_file: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:DD

    static int sscape_pnp_upload_file(sscape_info* devc, char* fn)
    {
    ...
    ==> Disable intr
    save_flags(flags);
    cli();
    while ( len > 0 ) {
    ==> Missing restore
    if (sscape_pnp_wait_dma ( devc, 0 ) == 0) return 0;
    }

    restore_flags(flags);
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/drivers/usb/usb-ohci.c:886:ep_add_ed: ERROR:LCK:HOLD: leaving function holding lock `&::usb_ed_lock'

    really two bugs

    BUG:DD
    BUG:DD:ECOND

    static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int interval, int load)
    {
    ...
    ==> Lock
    spin_lock (&usb_ed_lock);
    if((ed->state & ED_DEL) || (ed->state & ED_URB_DEL))
    ==> Missing unlock 1
    return NULL; /* pending delete request */
    if (ed->state == ED_NEW) {
    ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
    OHCI_ALLOC (td, sizeof (*td)); /* dummy td; end of td list for ed */
    ==> Missing unlock 2
    if(!td) return NULL; /* out of memory */
    ...
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/ipv4/netfilter/ip_queue.c:258:ipq_receive_peer: ERROR:BH:DIS: leaving function with bottom half disabled

    BUG:NET:ECOND: I think...

    static int ipq_receive_peer(ipq_queue_t *q, ipq_peer_msg_t *m,
    unsigned char type, unsigned int len)
    {
    ==> Locking here
    spin_lock_bh(&q->lock);
    if (q->terminate || q->flushing)
    ==> Missing unlock?
    return -EBUSY;
    spin_unlock_bh(&q->lock);
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/ipv4/netfilter/ip_queue.c:258:ipq_receive_peer: ERROR:LCK:HOLD: leaving function holding lock `(::ipq_receive_peer (::ipq_queue_t *, ::ipq_peer_msg_t *, unsigned char, unsigned int)::q + 20)'

    BUG:NET:ECOND: same as above
    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/ipv6/ip6_flowlabel.c:405:ipv6_flowlabel_opt: ERROR:BH:DIS: leaving function with bottom half disabled

    BUG:NET

    int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen)
    {
    switch (freq.flr_action) {
    ...
    case IPV6_FL_A_RENEW:
    ==> Lock here, disable BH
    read_lock_bh(&ip6_sk_fl_lock);
    for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) {
    if (sfl->fl->label == freq.flr_label)
    ==> Missing unlock, reenable
    return fl6_renew(sfl->fl, freq.flr_linger, freq.flr_expires);
    }
    read_unlock_bh(&ip6_sk_fl_lock);

    if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
    fl = fl_lookup(freq.flr_label);
    if (fl) {
    err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
    fl_release(fl);
    return err;
    }
    }
    return -ESRCH;
    ...
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/ipv6/ip6_flowlabel.c:405:ipv6_flowlabel_opt: ERROR:LCK:HOLD: leaving function holding lock `&::ip6_sk_fl_lock'

    BUG:NET: same as above
    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/ipx/af_spx.c:427:spx_transmit: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND

    static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
    {
    ...
    if(skb == NULL)
    {
    ...
    ==> Disable intr
    save_flags(flags);
    cli();
    skb = sock_alloc_send_skb(sk, size, 1, 0, &err);
    if(skb == NULL)
    ==> Missing restore
    return (-ENOMEM);
    skb_reserve(skb, offset);
    skb->h.raw = skb->nh.raw = skb_put(skb,sizeof(struct ipxspxhdr));
    restore_flags(flags);
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/ipx/af_spx.c:728:spx_sendmsg: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND

    static int spx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
    struct scm_cookie *scm)
    {
    ...
    ==> Disable intr
    cli();
    skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err);
    if(skb == NULL)
    ==> Missing enable
    return (err);
    sti();
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/ircomm/ircomm_core.c:490:ircomm_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND

    int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
    {
    struct ircomm_cb *self;
    unsigned long flags;
    int i=0;

    ==> Disable intr
    save_flags(flags);
    cli();

    len = 0;

    len += sprintf(buf+len, "Instance %d:\n", i++);

    self = (struct ircomm_cb *) hashbin_get_first(ircomm);
    while (self != NULL) {
    ==> Missing restore
    ASSERT(self->magic == IRCOMM_MAGIC, return len;);

    self = (struct ircomm_cb *) hashbin_get_next(ircomm);
    }
    restore_flags(flags);

    return len;
    }

    The macro-expanded version of the above ASSERT is:

    if(!( self->magic == 0x98347298 )) {
    printk( "Assertion failed! %s,%s,%s,line=%d\n",
    "self->magic == IRCOMM_MAGIC",
    "ircomm_core.c","" ,504);
    return len;
    } ;

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/ircomm/ircomm_tty.c:499:ircomm_tty_close: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND
    BUG:NET:ECOND

    static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
    {
    ...
    ==> Disable intr
    save_flags(flags);
    cli();

    ==> Missing restore
    ASSERT(self != NULL, return;);
    ==> Missing restore
    ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/iriap.c:971:irias_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND
    BUG:NET:ECOND

    int irias_proc_read(char *buf, char **start, off_t offset, int len)
    {
    ==> Disable intr
    save_flags( flags);
    cli();
    while ( obj != NULL) {
    ==> Missing restore
    ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
    ...
    while (attrib != NULL) {
    ==> Missing restore
    ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
    ...
    }

    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/irlan/irlan_common.c:1158:irlan_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND

    static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
    {
    struct irlan_cb *self;
    unsigned long flags;

    ==> Disable intr
    save_flags(flags);
    cli();

    while (self != NULL) {
    ==> Missing restore
    ASSERT(self->magic == IRLAN_MAGIC, return len;);
    ...
    }
    restore_flags(flags);

    return len;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/irlap.c:1134:irlap_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND
    BUG:NET:ECOND

    int irlap_proc_read(char *buf, char **start, off_t offset, int len)
    {
    struct irlap_cb *self;
    unsigned long flags;
    int i = 0;

    ==> Disable intr
    save_flags(flags);
    cli();

    len = 0;

    self = (struct irlap_cb *) hashbin_get_first(irlap);
    while (self != NULL) {
    ==> Missing restore
    ASSERT(self != NULL, return -ENODEV;);
    ==> Missing restore
    ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
    }
    ...
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/irlmp.c:1498:irlmp_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET:ECOND
    BUG:NET:ECOND

    int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
    {
    ==> Disable intr
    save_flags( flags);
    cli();
    ...
    while (self != NULL) {
    ==> Missing restore
    ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
    ...
    }
    while (lap != NULL) {
    ...
    while (self != NULL) {
    ==> Missing restore
    ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
    ...
    }
    ...
    }
    restore_flags(flags);

    return len;
    }

    --------------------------------------------------------------------------------
    /home/acc/linux-2.3.99/net/irda/irttp.c:1507:irttp_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled

    BUG:NET

    int irttp_proc_read(char *buf, char **start, off_t offset, int len)
    {
    ...
    ==> Disable intr
    save_flags(flags);
    cli();
    while (self != NULL) {
    if (!self || self->magic != TTP_TSAP_MAGIC)
    ==> Missing restore
    return len;
    ...
    }
    ...
    }

    \
     
     \ /
      Last update: 2005-03-22 13:58    [W:0.113 / U:31.380 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site