On Fri, Jan 30, 2015 at 02:34:42PM -0700, Todd C. Miller wrote:
> I think the simplest fix is to just move the m_free to the bad:
> label.

sosetopt() calls m_free() and then it is called again.  So it is a
double free.

I would move the so->so_proto check between the if (name == -1) and
the if (lsa.optlen > MLEN) block.  There m has not been allocated.

Untested as I do not have an i386 right now.

bluhm

Index: sys/compat/linux/linux_socket.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/compat/linux/linux_socket.c,v
retrieving revision 1.59
diff -u -p -r1.59 linux_socket.c
--- sys/compat/linux/linux_socket.c     21 Jan 2015 13:47:45 -0000      1.59
+++ sys/compat/linux/linux_socket.c     30 Jan 2015 21:51:05 -0000
@@ -962,6 +962,14 @@ linux_setsockopt(p, v, retval)
                error = EINVAL;
                goto bad;
        }
+       so = (struct socket *)fp->f_data;
+       if (so->so_proto && level == IPPROTO_TCP && name == TCP_NODELAY && 
+           so->so_proto->pr_domain->dom_family == AF_LOCAL &&
+           so->so_proto->pr_protocol == PF_LOCAL) {
+               /* ignore it */
+               error = 0;
+               goto bad;
+       }
        if (lsa.optlen > MLEN) {
                error = EINVAL;
                goto bad;
@@ -974,14 +982,6 @@ linux_setsockopt(p, v, retval)
                        goto bad;
                }
                m->m_len = lsa.optlen;
-       }
-       so = (struct socket *)fp->f_data;
-       if (so->so_proto && level == IPPROTO_TCP && name == TCP_NODELAY && 
-           so->so_proto->pr_domain->dom_family == AF_LOCAL &&
-           so->so_proto->pr_protocol == PF_LOCAL) {
-               /* ignore it */
-               error = 0;
-               goto bad;
        }
        error = sosetopt(so, level, name, m);
 bad:

Reply via email to