Commit 1b739388 authored by Chris Wulff's avatar Chris Wulff Committed by Greg Kroah-Hartman

usb: gadget: u_audio: Fix race condition use of controls after free during gadget unbind.

Hang on to the control IDs instead of pointers since those are correctly
handled with locks.

Fixes: 8fe9a03f ("usb: gadget: u_audio: Rate ctl notifies about current srate (0=stopped)")
Fixes: c565ad07 ("usb: gadget: u_audio: Support multiple sampling rates")
Fixes: 02de698c ("usb: gadget: u_audio: add bi-directional volume and mute support")
Signed-off-by: default avatarChris Wulff <chris.wulff@biamp.com>
Link: https://lore.kernel.org/stable/CO1PR17MB5419C2BF44D400E4E620C1ADE1172%40CO1PR17MB5419.namprd17.prod.outlook.com
Link: https://lore.kernel.org/r/CO1PR17MB5419C2BF44D400E4E620C1ADE1172@CO1PR17MB5419.namprd17.prod.outlook.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c5b324b1
...@@ -57,13 +57,13 @@ struct uac_rtd_params { ...@@ -57,13 +57,13 @@ struct uac_rtd_params {
/* Volume/Mute controls and their state */ /* Volume/Mute controls and their state */
int fu_id; /* Feature Unit ID */ int fu_id; /* Feature Unit ID */
struct snd_kcontrol *snd_kctl_volume; struct snd_ctl_elem_id snd_kctl_volume_id;
struct snd_kcontrol *snd_kctl_mute; struct snd_ctl_elem_id snd_kctl_mute_id;
s16 volume_min, volume_max, volume_res; s16 volume_min, volume_max, volume_res;
s16 volume; s16 volume;
int mute; int mute;
struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */ struct snd_ctl_elem_id snd_kctl_rate_id; /* read-only current rate */
int srate; /* selected samplerate */ int srate; /* selected samplerate */
int active; /* playback/capture running */ int active; /* playback/capture running */
...@@ -494,14 +494,13 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep) ...@@ -494,14 +494,13 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
static void set_active(struct uac_rtd_params *prm, bool active) static void set_active(struct uac_rtd_params *prm, bool active)
{ {
// notifying through the Rate ctrl // notifying through the Rate ctrl
struct snd_kcontrol *kctl = prm->snd_kctl_rate;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&prm->lock, flags); spin_lock_irqsave(&prm->lock, flags);
if (prm->active != active) { if (prm->active != active) {
prm->active = active; prm->active = active;
snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
&kctl->id); &prm->snd_kctl_rate_id);
} }
spin_unlock_irqrestore(&prm->lock, flags); spin_unlock_irqrestore(&prm->lock, flags);
} }
...@@ -807,7 +806,7 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val) ...@@ -807,7 +806,7 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
if (change) if (change)
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
&prm->snd_kctl_volume->id); &prm->snd_kctl_volume_id);
return 0; return 0;
} }
...@@ -856,7 +855,7 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val) ...@@ -856,7 +855,7 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
if (change) if (change)
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
&prm->snd_kctl_mute->id); &prm->snd_kctl_mute_id);
return 0; return 0;
} }
...@@ -1331,7 +1330,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, ...@@ -1331,7 +1330,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
err = snd_ctl_add(card, kctl); err = snd_ctl_add(card, kctl);
if (err < 0) if (err < 0)
goto snd_fail; goto snd_fail;
prm->snd_kctl_mute = kctl; prm->snd_kctl_mute_id = kctl->id;
prm->mute = 0; prm->mute = 0;
} }
...@@ -1359,7 +1358,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, ...@@ -1359,7 +1358,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
err = snd_ctl_add(card, kctl); err = snd_ctl_add(card, kctl);
if (err < 0) if (err < 0)
goto snd_fail; goto snd_fail;
prm->snd_kctl_volume = kctl; prm->snd_kctl_volume_id = kctl->id;
prm->volume = fu->volume_max; prm->volume = fu->volume_max;
prm->volume_max = fu->volume_max; prm->volume_max = fu->volume_max;
prm->volume_min = fu->volume_min; prm->volume_min = fu->volume_min;
...@@ -1383,7 +1382,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, ...@@ -1383,7 +1382,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
err = snd_ctl_add(card, kctl); err = snd_ctl_add(card, kctl);
if (err < 0) if (err < 0)
goto snd_fail; goto snd_fail;
prm->snd_kctl_rate = kctl; prm->snd_kctl_rate_id = kctl->id;
} }
strscpy(card->driver, card_name); strscpy(card->driver, card_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment