git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
ALSA: timer: Fix race at concurrent reads
[pandora-kernel.git]
/
sound
/
core
/
timer.c
diff --git
a/sound/core/timer.c
b/sound/core/timer.c
index
9198fe2
..
beb41ec
100644
(file)
--- a/
sound/core/timer.c
+++ b/
sound/core/timer.c
@@
-1890,6
+1890,7
@@
static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
{
struct snd_timer_user *tu;
long result = 0, unit;
{
struct snd_timer_user *tu;
long result = 0, unit;
+ int qhead;
int err = 0;
tu = file->private_data;
int err = 0;
tu = file->private_data;
@@
-1901,7
+1902,7
@@
static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
err = -EAGAIN;
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
err = -EAGAIN;
-
break
;
+
goto _error
;
}
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_INTERRUPTIBLE);
@@
-1916,38
+1917,33
@@
static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
if (signal_pending(current)) {
err = -ERESTARTSYS;
if (signal_pending(current)) {
err = -ERESTARTSYS;
-
break
;
+
goto _error
;
}
}
}
}
+ qhead = tu->qhead++;
+ tu->qhead %= tu->queue_size;
spin_unlock_irq(&tu->qlock);
spin_unlock_irq(&tu->qlock);
- if (err < 0)
- goto _error;
if (tu->tread) {
if (tu->tread) {
- if (copy_to_user(buffer, &tu->tqueue[
tu->qhead++
],
- sizeof(struct snd_timer_tread)))
{
+ if (copy_to_user(buffer, &tu->tqueue[
qhead
],
+ sizeof(struct snd_timer_tread)))
err = -EFAULT;
err = -EFAULT;
- goto _error;
- }
} else {
} else {
- if (copy_to_user(buffer, &tu->queue[
tu->qhead++
],
- sizeof(struct snd_timer_read)))
{
+ if (copy_to_user(buffer, &tu->queue[
qhead
],
+ sizeof(struct snd_timer_read)))
err = -EFAULT;
err = -EFAULT;
- goto _error;
- }
}
}
- tu->qhead %= tu->queue_size;
-
- result += unit;
- buffer += unit;
-
spin_lock_irq(&tu->qlock);
tu->qused--;
spin_lock_irq(&tu->qlock);
tu->qused--;
+ if (err < 0)
+ goto _error;
+ result += unit;
+ buffer += unit;
}
}
- spin_unlock_irq(&tu->qlock);
_error:
_error:
+ spin_unlock_irq(&tu->qlock);
return result > 0 ? result : err;
}
return result > 0 ? result : err;
}