From 54c7c33ce2cf80a561fcc5f83099c9150de6fe44 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Wed, 15 Aug 2012 19:58:28 -0700 Subject: [PATCH] USB: gadget: f_audio_source: Fix use after free in audio_unbind When USB was disconnected, we were freeing our audio_dev struct in audio_unbind before the audio system had cleaned up, resulting in a hang in audio_pcm_close. We now statically allocate the audio_dev struct to avoid this problem. Change-Id: I58ad21eaa20dcf4aa74ee614ef3b6ed2c91d52a1 Signed-off-by: Mike Lockwood --- drivers/usb/gadget/f_audio_source.c | 40 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/usb/gadget/f_audio_source.c b/drivers/usb/gadget/f_audio_source.c index ba8e007c7969..fe221c51cbfb 100644 --- a/drivers/usb/gadget/f_audio_source.c +++ b/drivers/usb/gadget/f_audio_source.c @@ -243,7 +243,6 @@ struct audio_dev { struct list_head idle_reqs; struct usb_ep *in_ep; - struct usb_endpoint_descriptor *in_desc; spinlock_t lock; @@ -620,7 +619,10 @@ audio_unbind(struct usb_configuration *c, struct usb_function *f) audio_request_free(req, audio->in_ep); snd_card_free_when_closed(audio->card); - kfree(audio); + audio->card = NULL; + audio->pcm = NULL; + audio->substream = NULL; + audio->in_ep = NULL; } static void audio_pcm_playback_start(struct audio_dev *audio) @@ -736,6 +738,19 @@ static int audio_pcm_playback_trigger(struct snd_pcm_substream *substream, return ret; } +static struct audio_dev _audio_dev = { + .func = { + .name = "audio_source", + .bind = audio_bind, + .unbind = audio_unbind, + .set_alt = audio_set_alt, + .setup = audio_setup, + .disable = audio_disable, + }, + .lock = __SPIN_LOCK_UNLOCKED(_audio_dev.lock), + .idle_reqs = LIST_HEAD_INIT(_audio_dev.idle_reqs), +}; + static struct snd_pcm_ops audio_playback_ops = { .open = audio_pcm_open, .close = audio_pcm_close, @@ -758,27 +773,12 @@ int audio_source_bind_config(struct usb_configuration *c, config->card = -1; config->device = -1; - audio = kzalloc(sizeof *audio, GFP_KERNEL); - if (!audio) - return -ENOMEM; - - audio->func.name = "audio_source"; - - spin_lock_init(&audio->lock); - - audio->func.bind = audio_bind; - audio->func.unbind = audio_unbind; - audio->func.set_alt = audio_set_alt; - audio->func.setup = audio_setup; - audio->func.disable = audio_disable; - audio->in_desc = &fs_as_in_ep_desc; - - INIT_LIST_HEAD(&audio->idle_reqs); + audio = &_audio_dev; err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &card); if (err) - goto snd_card_fail; + return err; snd_card_set_dev(card, &c->cdev->gadget->dev); @@ -817,7 +817,5 @@ add_fail: register_fail: pcm_fail: snd_card_free(audio->card); -snd_card_fail: - kfree(audio); return err; } -- 2.34.1