Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: Fix card refcount unbalance

There are uncovered cases whether the card refcount introduced by the
commit a0830dbd isn't properly increased or decreased:
- OSS PCM and mixer success paths
- When lookup function gets NULL

This patch fixes these places.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=50251

Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+8 -4
+1
sound/core/oss/mixer_oss.c
··· 76 76 snd_card_unref(card); 77 77 return -EFAULT; 78 78 } 79 + snd_card_unref(card); 79 80 return 0; 80 81 } 81 82
+1
sound/core/oss/pcm_oss.c
··· 2454 2454 mutex_unlock(&pcm->open_mutex); 2455 2455 if (err < 0) 2456 2456 goto __error; 2457 + snd_card_unref(pcm->card); 2457 2458 return err; 2458 2459 2459 2460 __error:
+4 -2
sound/core/pcm_native.c
··· 2122 2122 pcm = snd_lookup_minor_data(iminor(inode), 2123 2123 SNDRV_DEVICE_TYPE_PCM_PLAYBACK); 2124 2124 err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); 2125 - snd_card_unref(pcm->card); 2125 + if (pcm) 2126 + snd_card_unref(pcm->card); 2126 2127 return err; 2127 2128 } 2128 2129 ··· 2136 2135 pcm = snd_lookup_minor_data(iminor(inode), 2137 2136 SNDRV_DEVICE_TYPE_PCM_CAPTURE); 2138 2137 err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); 2139 - snd_card_unref(pcm->card); 2138 + if (pcm) 2139 + snd_card_unref(pcm->card); 2140 2140 return err; 2141 2141 } 2142 2142
+1 -1
sound/core/sound.c
··· 114 114 mreg = snd_minors[minor]; 115 115 if (mreg && mreg->type == type) { 116 116 private_data = mreg->private_data; 117 - if (mreg->card_ptr) 117 + if (private_data && mreg->card_ptr) 118 118 atomic_inc(&mreg->card_ptr->refcount); 119 119 } else 120 120 private_data = NULL;
+1 -1
sound/core/sound_oss.c
··· 54 54 mreg = snd_oss_minors[minor]; 55 55 if (mreg && mreg->type == type) { 56 56 private_data = mreg->private_data; 57 - if (mreg->card_ptr) 57 + if (private_data && mreg->card_ptr) 58 58 atomic_inc(&mreg->card_ptr->refcount); 59 59 } else 60 60 private_data = NULL;