ALSA: timer: Use deferred fasync helper
authorTakashi Iwai <tiwai@suse.de>
Thu, 28 Jul 2022 12:59:43 +0000 (14:59 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Aug 2022 09:09:31 +0000 (11:09 +0200)
[ Upstream commit 95cc637c1afd83fb7dd3d7c8a53710488f4caf9c ]

For avoiding the potential deadlock via kill_fasync() call, use the
new fasync helpers to defer the invocation from PCI API.  Note that
it's merely a workaround.

Reported-by: syzbot+1ee0910eca9c94f71f25@syzkaller.appspotmail.com
Reported-by: syzbot+49b10793b867871ee26f@syzkaller.appspotmail.com
Reported-by: syzbot+8285e973a41b5aa68902@syzkaller.appspotmail.com
Link: https://lore.kernel.org/r/20220728125945.29533-3-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
sound/core/timer.c

index 596ba572d6c499595260aa63d7425f0d8809a92b..1f5f05e76e59bf17dd051b4094db1cb72e6c7e68 100644 (file)
@@ -74,7 +74,7 @@ struct snd_timer_user {
        unsigned int filter;
        struct timespec tstamp;         /* trigger tstamp */
        wait_queue_head_t qchange_sleep;
-       struct fasync_struct *fasync;
+       struct snd_fasync *fasync;
        struct mutex ioctl_lock;
 };
 
@@ -1293,7 +1293,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
        }
       __wake:
        spin_unlock(&tu->qlock);
-       kill_fasync(&tu->fasync, SIGIO, POLL_IN);
+       snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);
        wake_up(&tu->qchange_sleep);
 }
 
@@ -1330,7 +1330,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
        spin_lock_irqsave(&tu->qlock, flags);
        snd_timer_user_append_to_tqueue(tu, &r1);
        spin_unlock_irqrestore(&tu->qlock, flags);
-       kill_fasync(&tu->fasync, SIGIO, POLL_IN);
+       snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);
        wake_up(&tu->qchange_sleep);
 }
 
@@ -1397,7 +1397,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
        spin_unlock(&tu->qlock);
        if (append == 0)
                return;
-       kill_fasync(&tu->fasync, SIGIO, POLL_IN);
+       snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);
        wake_up(&tu->qchange_sleep);
 }
 
@@ -1439,6 +1439,7 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
                if (tu->timeri)
                        snd_timer_close(tu->timeri);
                mutex_unlock(&tu->ioctl_lock);
+               snd_fasync_free(tu->fasync);
                kfree(tu->queue);
                kfree(tu->tqueue);
                kfree(tu);
@@ -2026,7 +2027,7 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on)
        struct snd_timer_user *tu;
 
        tu = file->private_data;
-       return fasync_helper(fd, file, on, &tu->fasync);
+       return snd_fasync_helper(fd, file, on, &tu->fasync);
 }
 
 static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,