On Fri, 30 Jan 2015 22:55:06 +0100, Alexander Bluhm wrote:

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

Whoops, I didn't notice that the non-error case also falls thought
to the "bad" label.  We could just do what sys_setsockopt() does
and zero out m after calling sosetopt().

 - todd

Index: sys/compat/linux/linux_socket.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_socket.c,v
retrieving revision 1.59
diff -u -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 22:56:40 -0000
@@ -969,10 +969,8 @@
        if (lsa.optval != NULL) {
                m = m_get(M_WAIT, MT_SOOPTS);
                error = copyin(lsa.optval, mtod(m, caddr_t), lsa.optlen);
-               if (error) {
-                       (void) m_free(m);
+               if (error)
                        goto bad;
-               }
                m->m_len = lsa.optlen;
        }
        so = (struct socket *)fp->f_data;
@@ -984,7 +982,10 @@
                goto bad;
        }
        error = sosetopt(so, level, name, m);
+       m = NULL;
 bad:
+       if (m)
+               m_free(m);
        FRELE(fp, p);
        return (error);
 }

Reply via email to