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: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
591c5f8a59
commit
35a7475dc8
@ -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);
|
||||
|
||||
@ -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) {
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user