| From 5c06d68bc2a174a6b82dce9f100f55173b9a5189 Mon Sep 17 00:00:00 2001 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Tue, 12 Jan 2016 14:03:33 +0100 |
| Subject: ALSA: usb-audio: Avoid calling usb_autopm_put_interface() at disconnect |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| commit 5c06d68bc2a174a6b82dce9f100f55173b9a5189 upstream. |
| |
| 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 |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| sound/usb/card.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/sound/usb/card.c |
| +++ b/sound/usb/card.c |
| @@ -675,6 +675,8 @@ int snd_usb_autoresume(struct snd_usb_au |
| |
| void snd_usb_autosuspend(struct snd_usb_audio *chip) |
| { |
| + if (atomic_read(&chip->shutdown)) |
| + return; |
| if (atomic_dec_and_test(&chip->active)) |
| usb_autopm_put_interface(chip->pm_intf); |
| } |