Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1678ec00 authored by Al Viro's avatar Al Viro
Browse files

mISDN: fix misdn_add_timer()/misdn_del_timer() race



do add_timer() *before* unlocking dev->lock, or unpleasant things can
happen if misdn_del_timer() on another CPU finds the sucker, calls
del_timer_sync() (which does nothing, since we hadn't started the
timer yet) and frees it, just as we get around to add_timer()...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1b108956
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -173,7 +173,6 @@ static int
misdn_add_timer(struct mISDNtimerdev *dev, int timeout)
{
	int			id;
	u_long			flags;
	struct mISDNtimer	*timer;

	if (!timeout) {
@@ -184,19 +183,16 @@ misdn_add_timer(struct mISDNtimerdev *dev, int timeout)
		timer = kzalloc(sizeof(struct mISDNtimer), GFP_KERNEL);
		if (!timer)
			return -ENOMEM;
		spin_lock_irqsave(&dev->lock, flags);
		timer->id = dev->next_id++;
		timer->dev = dev;
		setup_timer(&timer->tl, dev_expire_timer, (long)timer);
		spin_lock_irq(&dev->lock);
		id = timer->id = dev->next_id++;
		if (dev->next_id < 0)
			dev->next_id = 1;
		list_add_tail(&timer->list, &dev->pending);
		spin_unlock_irqrestore(&dev->lock, flags);
		timer->dev = dev;
		timer->tl.data = (long)timer;
		timer->tl.function = dev_expire_timer;
		init_timer(&timer->tl);
		timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000);
		add_timer(&timer->tl);
		id = timer->id;
		spin_unlock_irq(&dev->lock);
	}
	return id;
}