Another integer overflow: A recv() call with a size of 2^32 bytes causes
soreceive() to spin in an endless loop, resulting in a system freeze.
The diff below prevents this behaviour by establishing an upper bound
for uio_resid before assigning the value to an integer variable with
smaller width. Also the 'offset' and 'resid' variables are converted to
use the correct integer types.

cheers,
natano

Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.144
diff -u -p -u -r1.144 uipc_socket.c
--- kern/uipc_socket.c  5 Dec 2015 10:11:53 -0000       1.144
+++ kern/uipc_socket.c  31 Dec 2015 21:26:01 -0000
@@ -613,13 +613,14 @@ soreceive(struct socket *so, struct mbuf
 {
        struct mbuf *m, **mp;
        struct mbuf *cm;
-       int flags, len, error, s, offset;
+       int flags, len, error, s;
+       u_long offset;
        struct protosw *pr = so->so_proto;
        struct mbuf *nextrecord;
        int moff, type = 0;
        size_t orig_resid = uio->uio_resid;
        int uio_error = 0;
-       int resid;
+       size_t resid;
 
        mp = mp0;
        if (paddr)
@@ -639,8 +640,8 @@ soreceive(struct socket *so, struct mbuf
                if (error)
                        goto bad;
                do {
-                       error = uiomovei(mtod(m, caddr_t),
-                           (int) min(uio->uio_resid, m->m_len), uio);
+                       error = uiomove(mtod(m, caddr_t),
+                           ulmin(uio->uio_resid, m->m_len), uio);
                        m = m_free(m);
                } while (uio->uio_resid && error == 0 && m);
 bad:
@@ -833,11 +834,9 @@ dontblock:
                        panic("receive 3");
 #endif
                so->so_state &= ~SS_RCVATMARK;
-               len = uio->uio_resid;
+               len = ulmin(uio->uio_resid, m->m_len - moff);
                if (so->so_oobmark && len > so->so_oobmark - offset)
                        len = so->so_oobmark - offset;
-               if (len > m->m_len - moff)
-                       len = m->m_len - moff;
                /*
                 * If mp is set, just pass back the mbufs.
                 * Otherwise copy them out via the uio, then free.

Reply via email to