summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandanaKishori Chiluveru <cchilu@codeaurora.org>2014-03-11 17:09:50 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-26 03:29:37 -0700
commita510e932e4f77fa5f5d01c4223c3d2fb2f3a88c7 (patch)
tree183af8a4189d8bf03eb1c404889e2825b26aafd6
parentc5685ec0f3941352bad2535c8612058563ff064a (diff)
usb: gadget: Fix synchronization issue between f_audio_source
Race is happening when both audio_pcm_close() and audio_send() executes in parallel. When the PCM session is closed, the substream attribute of the audio_dev structure is set to NULL in audio_pcm_close(). As there is no synchronization protection for the audio_dev subtream attributes in audio_send(), it is causing NULL pointer dereference. Hence fixing the issue by adding proper synchronization protection for the audio_dev subtream attributes in audio_send(). CRs-Fixed: 613498 Change-Id: Id9ab0d4e347b8bb2f551f9033829e541bdcaf0e8 Signed-off-by: ChandanaKishori Chiluveru <cchilu@codeaurora.org> Signed-off-by: Tarun Gupta <tarung@codeaurora.org>
-rw-r--r--drivers/usb/gadget/function/f_audio_source.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 51ab794ef6f9..ab7441fcf66f 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -369,15 +369,22 @@ static void audio_send(struct audio_dev *audio)
s64 msecs;
s64 frames;
ktime_t now;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->lock, flags);
/* audio->substream will be null if we have been closed */
- if (!audio->substream)
+ if (!audio->substream) {
+ spin_unlock_irqrestore(&audio->lock, flags);
return;
+ }
/* audio->buffer_pos will be null if we have been stopped */
- if (!audio->buffer_pos)
+ if (!audio->buffer_pos) {
+ spin_unlock_irqrestore(&audio->lock, flags);
return;
+ }
runtime = audio->substream->runtime;
+ spin_unlock_irqrestore(&audio->lock, flags);
/* compute number of frames to send */
now = ktime_get();
@@ -400,8 +407,21 @@ static void audio_send(struct audio_dev *audio)
while (frames > 0) {
req = audio_req_get(audio);
- if (!req)
+ spin_lock_irqsave(&audio->lock, flags);
+ /* audio->substream will be null if we have been closed */
+ if (!audio->substream) {
+ spin_unlock_irqrestore(&audio->lock, flags);
+ return;
+ }
+ /* audio->buffer_pos will be null if we have been stopped */
+ if (!audio->buffer_pos) {
+ spin_unlock_irqrestore(&audio->lock, flags);
+ return;
+ }
+ if (!req) {
+ spin_unlock_irqrestore(&audio->lock, flags);
break;
+ }
length = frames_to_bytes(runtime, frames);
if (length > IN_EP_MAX_PACKET_SIZE)
@@ -427,6 +447,7 @@ static void audio_send(struct audio_dev *audio)
}
req->length = length;
+ spin_unlock_irqrestore(&audio->lock, flags);
ret = usb_ep_queue(audio->in_ep, req, GFP_ATOMIC);
if (ret < 0) {
pr_err("usb_ep_queue failed ret: %d\n", ret);