On Fri, Jan 30, 2015 at 03:57:12PM -0700, Todd C. Miller wrote:
> 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().
Let's take this fix. OK bluhm@
>
> - 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);
> }