Skip to content

Commit

Permalink
staging: comedi: allow buffer wraparound in comedi_write()
Browse files Browse the repository at this point in the history
`comedi_write()` copies data from the user buffer to the acquisition
data buffer, which is cyclic, using a single call to `copy_from_user()`.
It currently avoids having to deal with wraparound of the cyclic buffer
by limiting the amount it copies (and the amount returned to the user).
Change it to deal with the wraparound using two calls to
`copy_from_user()` if necessary.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Ian Abbott authored and Greg Kroah-Hartman committed Dec 21, 2015
1 parent 591c5f8 commit 35a7475
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions drivers/staging/comedi/comedi_fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2346,6 +2346,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
add_wait_queue(&async->wait_head, &wait);
while (count == 0 && !retval) {
unsigned runflags;
unsigned int wp, n1, n2;

set_current_state(TASK_INTERRUPTIBLE);

Expand All @@ -2360,9 +2361,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
/* Allocate all free buffer space. */
comedi_buf_write_alloc(s, async->prealloc_bufsz);
m = comedi_buf_write_n_allocated(s);
/* Avoid buffer wraparound. */
if (async->buf_write_ptr + m > async->prealloc_bufsz)
m = async->prealloc_bufsz - async->buf_write_ptr;
n = min_t(size_t, m, nbytes);

if (n == 0) {
Expand All @@ -2388,8 +2386,14 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
continue;
}

m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
buf, n);
wp = async->buf_write_ptr;
n1 = min(n, async->prealloc_bufsz - wp);
n2 = n - n1;
m = copy_from_user(async->prealloc_buf + wp, buf, n1);
if (m)
m += n2;
else if (n2)
m = copy_from_user(async->prealloc_buf, buf + n1, n2);
if (m) {
n -= m;
retval = -EFAULT;
Expand Down

0 comments on commit 35a7475

Please sign in to comment.