Messages in this thread | | | Date | Sat, 5 Aug 2000 15:06:07 -0700 | From | Andy Chou <> | Subject | Re: [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; ... } ... }
| |