aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@google.com>2012-08-15 19:58:28 -0700
committerSimon Wilson <simonwilson@google.com>2012-08-16 13:29:55 -0700
commit30e1f36b1b4d9c0ae734c0863b29b48ada8ebd1b (patch)
treef1503a2eca4856964a1874b683f3f9c28f201c8b /drivers/usb
parent44537a302ed5bccab183aa01d6f67cad95f9099b (diff)
downloadkernel_samsung_crespo-30e1f36b1b4d9c0ae734c0863b29b48ada8ebd1b.zip
kernel_samsung_crespo-30e1f36b1b4d9c0ae734c0863b29b48ada8ebd1b.tar.gz
kernel_samsung_crespo-30e1f36b1b4d9c0ae734c0863b29b48ada8ebd1b.tar.bz2
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 <lockwood@google.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/f_audio_source.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/drivers/usb/gadget/f_audio_source.c b/drivers/usb/gadget/f_audio_source.c
index ba8e007..fe221c5 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;
}