Commit 35a7475d authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman

staging: comedi: allow buffer wraparound in comedi_write()

`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: default avatarIan Abbott <abbotti@mev.co.uk>
Reviewed-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 591c5f8a
...@@ -2346,6 +2346,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, ...@@ -2346,6 +2346,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
add_wait_queue(&async->wait_head, &wait); add_wait_queue(&async->wait_head, &wait);
while (count == 0 && !retval) { while (count == 0 && !retval) {
unsigned runflags; unsigned runflags;
unsigned int wp, n1, n2;
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
...@@ -2360,9 +2361,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, ...@@ -2360,9 +2361,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
/* Allocate all free buffer space. */ /* Allocate all free buffer space. */
comedi_buf_write_alloc(s, async->prealloc_bufsz); comedi_buf_write_alloc(s, async->prealloc_bufsz);
m = comedi_buf_write_n_allocated(s); 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); n = min_t(size_t, m, nbytes);
if (n == 0) { if (n == 0) {
...@@ -2388,8 +2386,14 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, ...@@ -2388,8 +2386,14 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
continue; continue;
} }
m = copy_from_user(async->prealloc_buf + async->buf_write_ptr, wp = async->buf_write_ptr;
buf, n); 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) { if (m) {
n -= m; n -= m;
retval = -EFAULT; retval = -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment