From a4461f41b94cb52e0141af717dcf4ef6558c8e2e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 31 Oct 2013 15:01:37 +0000 Subject: ALSA: fix oops in snd_pcm_info() caused by ASoC DPCM Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = d5300000 [00000008] *pgd=0d265831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT ARM CPU: 0 PID: 2295 Comm: vlc Not tainted 3.11.0+ #755 task: dee74800 ti: e213c000 task.ti: e213c000 PC is at snd_pcm_info+0xc8/0xd8 LR is at 0x30232065 pc : [] lr : [<30232065>] psr: a0070013 sp : e213dea8 ip : d81cb0d0 fp : c05f7678 r10: c05f7770 r9 : fffffdfd r8 : 00000000 r7 : d8a968a8 r6 : d8a96800 r5 : d8a96200 r4 : d81cb000 r3 : 00000000 r2 : d81cb000 r1 : 00000001 r0 : d8a96200 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 15300019 DAC: 00000015 Process vlc (pid: 2295, stack limit = 0xe213c248) [] (snd_pcm_info) from [] (snd_pcm_info_user+0x34/0x9c) [] (snd_pcm_info_user) from [] (snd_pcm_control_ioctl+0x274/0x280) [] (snd_pcm_control_ioctl) from [] (snd_ctl_ioctl+0xc0/0x55c) [] (snd_ctl_ioctl) from [] (do_vfs_ioctl+0x80/0x31c) [] (do_vfs_ioctl) from [] (SyS_ioctl+0x3c/0x60) [] (SyS_ioctl) from [] (ret_fast_syscall+0x0/0x48) Code: e1a00005 e59530dc e3a01001 e1a02004 (e5933008) ---[ end trace cb3d9bdb8dfefb3c ]--- This is provoked when the ASoC front end is open along with its backend, (which causes the backend to have a runtime assigned to it) and then the SNDRV_CTL_IOCTL_PCM_INFO is requested for the (visible) backend device. Resolve this by ensuring that ASoC internal backend devices are not visible to userspace, just as the commentry for snd_pcm_new_internal() says it should be. Signed-off-by: Russell King Acked-by: Mark Brown Cc: [v3.4+] Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 17f45e8..e1e9e0c 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -49,6 +49,8 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->internal) + continue; if (pcm->card == card && pcm->device == device) return pcm; } @@ -60,6 +62,8 @@ static int snd_pcm_next(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->internal) + continue; if (pcm->card == card && pcm->device > device) return pcm->device; else if (pcm->card->number > card->number) -- cgit v1.1