diff options
author | 2017-08-22 09:13:36 +0000 | |
---|---|---|
committer | 2017-08-22 09:13:36 +0000 | |
commit | 0bad721a22b5b65b644fe726746ef68bc247f3bc (patch) | |
tree | 65b13693ba1979f2212fbddf01dc3692288faf15 /sys/kern | |
parent | Fix off by one overwrite. Covery CID 1452938. (diff) | |
download | wireguard-openbsd-0bad721a22b5b65b644fe726746ef68bc247f3bc.tar.xz wireguard-openbsd-0bad721a22b5b65b644fe726746ef68bc247f3bc.zip |
Make sogetopt(9) caller responsible for allocating an MT_SOOPTS mbuf.
Move a blocking memory allocation out of the socket lock and create
a simpler alloc/free pattern to review. Now both m_get() and m_free()
are in the same place.
Discussed with bluhm@.
Encouragements from deraadt@ and tedu@, ok kettenis@, florian@, visa@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/uipc_socket.c | 21 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 7 |
2 files changed, 8 insertions, 20 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index c499f46de04..369e32ecdc5 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.201 2017/08/10 19:20:43 mpi Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.202 2017/08/22 09:13:36 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -1755,30 +1755,24 @@ bad: } int -sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) +sogetopt(struct socket *so, int level, int optname, struct mbuf *m) { int error = 0; - struct mbuf *m; soassertlocked(so); if (level != SOL_SOCKET) { if (so->so_proto->pr_ctloutput) { - m = m_get(M_WAIT, MT_SOOPTS); m->m_len = 0; error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so, level, optname, m); - if (error) { - m_free(m); + if (error) return (error); - } - *mp = m; return (0); } else return (ENOPROTOOPT); } else { - m = m_get(M_WAIT, MT_SOOPTS); m->m_len = sizeof (int); switch (optname) { @@ -1856,13 +1850,10 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) level = dom->dom_protosw->pr_protocol; error = (*so->so_proto->pr_ctloutput) (PRCO_GETOPT, so, level, optname, m); - if (error) { - (void)m_free(m); + if (error) return (error); - } break; } - (void)m_free(m); return (ENOPROTOOPT); #ifdef SOCKET_SPLICE @@ -1887,17 +1878,13 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) &(unp->unp_connid), m->m_len); break; } - (void)m_free(m); return (ENOTCONN); } - (void)m_free(m); return (EOPNOTSUPP); default: - (void)m_free(m); return (ENOPROTOOPT); } - *mp = m; return (0); } } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 047f557274e..bc9b50cfac3 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.158 2017/08/10 19:20:43 mpi Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.159 2017/08/22 09:13:36 mpi Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -1014,9 +1014,10 @@ sys_getsockopt(struct proc *p, void *v, register_t *retval) goto out; } else valsize = 0; + m = m_get(M_WAIT, MT_SOOPTS); so = fp->f_data; s = solock(so); - error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), &m); + error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); sounlock(s); if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { if (valsize > m->m_len) @@ -1026,9 +1027,9 @@ sys_getsockopt(struct proc *p, void *v, register_t *retval) error = copyout(&valsize, SCARG(uap, avalsize), sizeof (valsize)); } + m_free(m); out: FRELE(fp, p); - m_free(m); return (error); } |