The uiomove() manual page states that "The lesser of n or uio->uio_resid bytes are copied." However, this is only true, when uio_resid ends up on an iovec boundary. Otherwise more bytes may be copied, even if they exceed uio_resid. The patch below changes uiomove() to actually never copy more than uio_resid bytes, as described in the manual.
Also, uiomove() assumes that the iovecs supplied to the function can accomodate the requested size, which is a reasonable assumption. But still, a KASSERT() might be a good idea to detect a mismatch as early as possible. While there I removed some diagnostic code outside of #ifdef DIAGNOSTIC. Index: kern/kern_subr.c =================================================================== RCS file: /cvs/src/sys/kern/kern_subr.c,v retrieving revision 1.45 diff -u -p -u -r1.45 kern_subr.c --- kern/kern_subr.c 11 Dec 2015 16:07:02 -0000 1.45 +++ kern/kern_subr.c 10 Jan 2016 11:10:38 -0000 @@ -51,20 +51,22 @@ uiomove(void *cp, size_t n, struct uio * struct iovec *iov; size_t cnt; int error = 0; - struct proc *p; - - p = uio->uio_procp; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) panic("uiomove: mode"); - if (uio->uio_segflg == UIO_USERSPACE && p != curproc) + if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) panic("uiomove: proc"); #endif - while (n > 0 && uio->uio_resid) { + + if (n > uio->uio_resid) + n = uio->uio_resid; + + while (n > 0) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { + KASSERT(uio->uio_iovcnt > 0); uio->uio_iov++; uio->uio_iovcnt--; continue; cheers, natano