diff options
author | 2017-09-01 15:05:31 +0000 | |
---|---|---|
committer | 2017-09-01 15:05:31 +0000 | |
commit | e09b1b7c399f82ae784da0bb3508c9e74fbd7692 (patch) | |
tree | 39a99b2b3f132da588e6d96ba211e45cf2f5b1e9 /sys/kern/uipc_socket.c | |
parent | Make 'tcpdump -v' decode RSN information elements in beacons (diff) | |
download | wireguard-openbsd-e09b1b7c399f82ae784da0bb3508c9e74fbd7692.tar.xz wireguard-openbsd-e09b1b7c399f82ae784da0bb3508c9e74fbd7692.zip |
Change sosetopt() to no longer free the mbuf it receives and change
all the callers to call m_freem(9).
Support from deraadt@ and tedu@, ok visa@, bluhm@
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r-- | sys/kern/uipc_socket.c | 81 |
1 files changed, 28 insertions, 53 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 369e32ecdc5..a54338e28a7 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.202 2017/08/22 09:13:36 mpi Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.203 2017/09/01 15:05:31 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -1558,17 +1558,16 @@ sowwakeup(struct socket *so) } int -sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) +sosetopt(struct socket *so, int level, int optname, struct mbuf *m) { int error = 0; - struct mbuf *m = m0; soassertlocked(so); if (level != SOL_SOCKET) { if (so->so_proto->pr_ctloutput) { error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, - level, optname, m0); + level, optname, m); return (error); } error = ENOPROTOOPT; @@ -1576,7 +1575,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) switch (optname) { case SO_BINDANY: if ((error = suser(curproc, 0)) != 0) /* XXX */ - goto bad; + return (error); break; } @@ -1585,10 +1584,8 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) case SO_LINGER: if (m == NULL || m->m_len != sizeof (struct linger) || mtod(m, struct linger *)->l_linger < 0 || - mtod(m, struct linger *)->l_linger > SHRT_MAX) { - error = EINVAL; - goto bad; - } + mtod(m, struct linger *)->l_linger > SHRT_MAX) + return (EINVAL); so->so_linger = mtod(m, struct linger *)->l_linger; /* FALLTHROUGH */ @@ -1602,10 +1599,8 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) case SO_OOBINLINE: case SO_TIMESTAMP: case SO_ZEROIZE: - if (m == NULL || m->m_len < sizeof (int)) { - error = EINVAL; - goto bad; - } + if (m == NULL || m->m_len < sizeof (int)) + return (EINVAL); if (*mtod(m, int *)) so->so_options |= optname; else @@ -1613,10 +1608,8 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) break; case SO_DONTROUTE: - if (m == NULL || m->m_len < sizeof (int)) { - error = EINVAL; - goto bad; - } + if (m == NULL || m->m_len < sizeof (int)) + return (EINVAL); if (*mtod(m, int *)) error = EOPNOTSUPP; break; @@ -1628,38 +1621,28 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) { u_long cnt; - if (m == NULL || m->m_len < sizeof (int)) { - error = EINVAL; - goto bad; - } + if (m == NULL || m->m_len < sizeof (int)) + return (EINVAL); cnt = *mtod(m, int *); if ((long)cnt <= 0) cnt = 1; switch (optname) { case SO_SNDBUF: - if (so->so_state & SS_CANTSENDMORE) { - error = EINVAL; - goto bad; - } + if (so->so_state & SS_CANTSENDMORE) + return (EINVAL); if (sbcheckreserve(cnt, so->so_snd.sb_wat) || - sbreserve(so, &so->so_snd, cnt)) { - error = ENOBUFS; - goto bad; - } + sbreserve(so, &so->so_snd, cnt)) + return (ENOBUFS); so->so_snd.sb_wat = cnt; break; case SO_RCVBUF: - if (so->so_state & SS_CANTRCVMORE) { - error = EINVAL; - goto bad; - } + if (so->so_state & SS_CANTRCVMORE) + return (EINVAL); if (sbcheckreserve(cnt, so->so_rcv.sb_wat) || - sbreserve(so, &so->so_rcv, cnt)) { - error = ENOBUFS; - goto bad; - } + sbreserve(so, &so->so_rcv, cnt)) + return (ENOBUFS); so->so_rcv.sb_wat = cnt; break; @@ -1683,16 +1666,12 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) struct timeval tv; int val; - if (m == NULL || m->m_len < sizeof (tv)) { - error = EINVAL; - goto bad; - } + if (m == NULL || m->m_len < sizeof (tv)) + return (EINVAL); memcpy(&tv, mtod(m, struct timeval *), sizeof tv); val = tvtohz(&tv); - if (val > USHRT_MAX) { - error = EDOM; - goto bad; - } + if (val > USHRT_MAX) + return (EDOM); switch (optname) { @@ -1714,7 +1693,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) level = dom->dom_protosw->pr_protocol; error = (*so->so_proto->pr_ctloutput) - (PRCO_SETOPT, so, level, optname, m0); + (PRCO_SETOPT, so, level, optname, m); return (error); } error = ENOPROTOOPT; @@ -1725,8 +1704,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) if (m == NULL) { error = sosplice(so, -1, 0, NULL); } else if (m->m_len < sizeof(int)) { - error = EINVAL; - goto bad; + return (EINVAL); } else if (m->m_len < sizeof(struct splice)) { error = sosplice(so, *mtod(m, int *), 0, NULL); } else { @@ -1744,13 +1722,10 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) } if (error == 0 && so->so_proto->pr_ctloutput) { (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, - level, optname, m0); - m = NULL; /* freed by protocol */ + level, optname, m); } } -bad: - if (m) - (void) m_free(m); + return (error); } |