Martin Natano wrote:
> 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.

Yes, it makes sense to make uiomove() behave as the manual says.
And I've seen code that manipulates the uio_resid fields outside of
uiomove (and then calls uiomove later; soreceive for example).
That means we can't enforce or always be sure that
uio_resid == the sum of all iov_len.

So the diff looks good to me.
 
> 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
> 

Reply via email to