diff options
author | Takashi Iwai <tiwai@suse.de> | 2016-01-12 14:03:33 +0100 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2016-04-06 10:58:39 -0400 |
commit | 46a190e6a3cd8223534614d306ab76b4811b6cc5 (patch) | |
tree | 4d2ecec762f8d5fbb828724fe40f0a5758feec37 | |
parent | 30e821e1c1f3a6a2d11616a7bb65da28da388f78 (diff) |
ALSA: usb-audio: Avoid calling usb_autopm_put_interface() at disconnect
[ Upstream commit 5c06d68bc2a174a6b82dce9f100f55173b9a5189 ]
ALSA PCM may still have a leftover instance after disconnection and
it delays its release. The problem is that the PCM close code path of
USB-audio driver has a call of snd_usb_autosuspend(). This involves
with the call of usb_autopm_put_interface() and it may lead to a
kernel Oops due to the NULL object like:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000190
IP: [<ffffffff815ae7ef>] usb_autopm_put_interface+0xf/0x30 PGD 0
Call Trace:
[<ffffffff8173bd94>] snd_usb_autosuspend+0x14/0x20
[<ffffffff817461bc>] snd_usb_pcm_close.isra.14+0x5c/0x90
[<ffffffff8174621f>] snd_usb_playback_close+0xf/0x20
[<ffffffff816ef58a>] snd_pcm_release_substream.part.36+0x3a/0x90
[<ffffffff816ef6b3>] snd_pcm_release+0xa3/0xb0
[<ffffffff816debb0>] snd_disconnect_release+0xd0/0xe0
[<ffffffff8114d417>] __fput+0x97/0x1d0
[<ffffffff8114d589>] ____fput+0x9/0x10
[<ffffffff8109e452>] task_work_run+0x72/0x90
[<ffffffff81088510>] do_exit+0x280/0xa80
[<ffffffff8108996a>] do_group_exit+0x3a/0xa0
[<ffffffff8109261f>] get_signal+0x1df/0x540
[<ffffffff81040903>] do_signal+0x23/0x620
[<ffffffff8114c128>] ? do_readv_writev+0x128/0x200
[<ffffffff810012e1>] prepare_exit_to_usermode+0x91/0xd0
[<ffffffff810013ba>] syscall_return_slowpath+0x9a/0x120
[<ffffffff817587cd>] ? __sys_recvmsg+0x5d/0x70
[<ffffffff810d2765>] ? ktime_get_ts64+0x45/0xe0
[<ffffffff8115dea0>] ? SyS_poll+0x60/0xf0
[<ffffffff818d2327>] int_ret_from_sys_call+0x25/0x8f
We have already a check of disconnection in snd_usb_autoresume(), but
the check is missing its counterpart. The fix is just to put the same
check in snd_usb_autosuspend(), too.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=109431
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
-rw-r--r-- | sound/usb/card.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index b6621bcba2dc..86cf7b585e01 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -679,6 +679,8 @@ void snd_usb_autosuspend(struct snd_usb_audio *chip) { if (chip->probing) return; + if (atomic_read(&chip->shutdown)) + return; if (atomic_dec_and_test(&chip->active)) usb_autopm_put_interface(chip->pm_intf); } |