Skip to content

Commit

Permalink
mISDN: fix the races with timers going off just as they are deleted
Browse files Browse the repository at this point in the history
timer callback in timerdev.c both accesses struct mISDNtimer it's
called for *and* moves it to dev->expired.  We need del_timer_sync(),
or we risk kfree() freeing it right under dev_expire_timer() *and*
dev->expired getting corrupted.

Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Al Viro committed Apr 29, 2013
1 parent 03feee3 commit c08c464
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions drivers/isdn/mISDN/timerdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,24 @@ static int
mISDN_close(struct inode *ino, struct file *filep)
{
struct mISDNtimerdev *dev = filep->private_data;
struct list_head *list = &dev->pending;
struct mISDNtimer *timer, *next;

if (*debug & DEBUG_TIMER)
printk(KERN_DEBUG "%s(%p,%p)\n", __func__, ino, filep);
list_for_each_entry_safe(timer, next, &dev->pending, list) {
del_timer(&timer->tl);

spin_lock_irq(&dev->lock);
while (!list_empty(list)) {
timer = list_first_entry(list, struct mISDNtimer, list);
spin_unlock_irq(&dev->lock);
del_timer_sync(&timer->tl);
spin_lock_irq(&dev->lock);
/* it might have been moved to ->expired */
list_del(&timer->list);
kfree(timer);
}
spin_unlock_irq(&dev->lock);

list_for_each_entry_safe(timer, next, &dev->expired, list) {
kfree(timer);
}
Expand Down

0 comments on commit c08c464

Please sign in to comment.