From e546a771ff8058ddf51f3505ae2bfa7da46c0771 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 8 Feb 2016 17:26:58 +0100 Subject: [PATCH] BACKPORT: ALSA: timer: Fix race at concurrent reads snd_timer_user_read() has a potential race among parallel reads, as qhead and qused are updated outside the critical section due to copy_to_user() calls. Move them into the critical section, and also sanitize the relevant code a bit. Bug: 37240993 Change-Id: I7358a57638ef23eb7f97341eaee1f0dd4ba2795a Cc: Signed-off-by: Takashi Iwai Signed-off-by: Siqi Lin (cherry picked from commit 4dff5c7b7093b19c19d3a100f8a3ad87cb7cd9e7) Signed-off-by: Francisco Franco --- sound/core/timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index c0c84119a980..6d731efbbef2 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1937,7 +1937,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, if (tu->disconnected) { err = -ENODEV; - break; + goto _error; } if (signal_pending(current)) { err = -ERESTARTSYS; @@ -1947,7 +1947,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, qhead = tu->qhead++; tu->qhead %= tu->queue_size; - tu->qused--; spin_unlock_irq(&tu->qlock); if (tu->tread) { @@ -1961,6 +1960,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, } spin_lock_irq(&tu->qlock); + tu->qused--; if (err < 0) goto _error; result += unit;