usb: gadget: u_audio: Fix race condition use of controls after free during gadget...
authorChris Wulff <Chris.Wulff@biamp.com>
Thu, 25 Apr 2024 15:18:01 +0000 (15:18 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 May 2024 16:26:06 +0000 (18:26 +0200)
Hang on to the control IDs instead of pointers since those are correctly
handled with locks.

Fixes: 8fe9a03f4331 ("usb: gadget: u_audio: Rate ctl notifies about current srate (0=stopped)")
Fixes: c565ad07ef35 ("usb: gadget: u_audio: Support multiple sampling rates")
Fixes: 02de698ca812 ("usb: gadget: u_audio: add bi-directional volume and mute support")
Signed-off-by: Chris 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.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/function/u_audio.c

index 1a634646bd24b436136e7042ffee89de248d4be5..efa3e3100333c00ab6e3699bfef2523c6bd71cb7 100644 (file)
@@ -57,13 +57,13 @@ struct uac_rtd_params {
 
   /* Volume/Mute controls and their state */
   int fu_id; /* Feature Unit ID */
-  struct snd_kcontrol *snd_kctl_volume;
-  struct snd_kcontrol *snd_kctl_mute;
+  struct snd_ctl_elem_id snd_kctl_volume_id;
+  struct snd_ctl_elem_id snd_kctl_mute_id;
   s16 volume_min, volume_max, volume_res;
   s16 volume;
   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 active; /* playback/capture running */
 
@@ -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)
 {
        // notifying through the Rate ctrl
-       struct snd_kcontrol *kctl = prm->snd_kctl_rate;
        unsigned long flags;
 
        spin_lock_irqsave(&prm->lock, flags);
        if (prm->active != active) {
                prm->active = active;
                snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                               &kctl->id);
+                               &prm->snd_kctl_rate_id);
        }
        spin_unlock_irqrestore(&prm->lock, flags);
 }
@@ -807,7 +806,7 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
 
        if (change)
                snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                               &prm->snd_kctl_volume->id);
+                               &prm->snd_kctl_volume_id);
 
        return 0;
 }
@@ -856,7 +855,7 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
 
        if (change)
                snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &prm->snd_kctl_mute->id);
+                              &prm->snd_kctl_mute_id);
 
        return 0;
 }
@@ -1331,7 +1330,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
                        err = snd_ctl_add(card, kctl);
                        if (err < 0)
                                goto snd_fail;
-                       prm->snd_kctl_mute = kctl;
+                       prm->snd_kctl_mute_id = kctl->id;
                        prm->mute = 0;
                }
 
@@ -1359,7 +1358,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
                        err = snd_ctl_add(card, kctl);
                        if (err < 0)
                                goto snd_fail;
-                       prm->snd_kctl_volume = kctl;
+                       prm->snd_kctl_volume_id = kctl->id;
                        prm->volume = fu->volume_max;
                        prm->volume_max = fu->volume_max;
                        prm->volume_min = fu->volume_min;
@@ -1383,7 +1382,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
                err = snd_ctl_add(card, kctl);
                if (err < 0)
                        goto snd_fail;
-               prm->snd_kctl_rate = kctl;
+               prm->snd_kctl_rate_id = kctl->id;
        }
 
        strscpy(card->driver, card_name);