diff options
author | 2012-09-20 12:34:18 +0000 | |
---|---|---|
committer | 2012-09-20 12:34:18 +0000 | |
commit | 579436d1d0adde6f1f386bb5a476ead36452c65b (patch) | |
tree | 17fb78a15a016ae602cd1d2a07839f64d412c30a | |
parent | Move the HTTP code into an extra file to make future changes easier to (diff) | |
download | wireguard-openbsd-579436d1d0adde6f1f386bb5a476ead36452c65b.tar.xz wireguard-openbsd-579436d1d0adde6f1f386bb5a476ead36452c65b.zip |
In somove() free the mbufs when necessary instead of freeing them
in the release path. Especially accessing m in a KDASSERT() could
go wrong.
OK claudio@
-rw-r--r-- | sys/kern/uipc_socket.c | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 6724bd4aaca..de3c9f01cf3 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.107 2012/09/19 20:00:32 bluhm Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.108 2012/09/20 12:34:18 bluhm Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -1151,7 +1151,7 @@ int somove(struct socket *so, int wait) { struct socket *sosp = so->so_splice; - struct mbuf *m = NULL, **mp, *nextrecord; + struct mbuf *m, **mp, *nextrecord; u_long len, off, oobmark; long space; int error = 0, maxreached = 0; @@ -1229,14 +1229,17 @@ somove(struct socket *so, int wait) SBLASTRECORDCHK(&so->so_rcv, "somove"); SBLASTMBUFCHK(&so->so_rcv, "somove"); - KDASSERT(m->m_nextpkt == NULL); KASSERT(so->so_rcv.sb_mb == so->so_rcv.sb_lastrecord); #ifdef SOCKBUF_DEBUG sbcheck(&so->so_rcv); #endif - /* Send window update to source peer if receive buffer has changed. */ - if (m && so->so_proto->pr_flags & PR_WANTRCVD && so->so_pcb) + /* m might be NULL if the loop did break during the first iteration. */ + if (m == NULL) + goto release; + + /* Send window update to source peer as receive buffer has changed. */ + if (so->so_proto->pr_flags & PR_WANTRCVD && so->so_pcb) (so->so_proto->pr_usrreq)(so, PRU_RCVD, NULL, (struct mbuf *)0L, NULL, NULL); @@ -1256,7 +1259,7 @@ somove(struct socket *so, int wait) * Handle oob data. If any malloc fails, ignore error. * TCP urgent data is not very reliable anyway. */ - while (m && ((state & SS_RCVATMARK) || oobmark) && + while (((state & SS_RCVATMARK) || oobmark) && (so->so_options & SO_OOBINLINE)) { struct mbuf *o = NULL; @@ -1268,14 +1271,15 @@ somove(struct socket *so, int wait) if (o) { error = (*sosp->so_proto->pr_usrreq)(sosp, PRU_SEND, m, NULL, NULL, NULL); - m = o; if (error) { if (sosp->so_state & SS_CANTSENDMORE) error = EPIPE; + m_freem(o); goto release; } len -= oobmark; so->so_splicelen += oobmark; + m = o; o = m_get(wait, MT_DATA); } oobmark = 0; @@ -1288,6 +1292,7 @@ somove(struct socket *so, int wait) if (error) { if (sosp->so_state & SS_CANTSENDMORE) error = EPIPE; + m_freem(m); goto release; } len -= 1; @@ -1302,23 +1307,18 @@ somove(struct socket *so, int wait) } /* Append all remaining data to drain socket. */ - if (m) { - if (so->so_rcv.sb_cc == 0 || maxreached) - sosp->so_state &= ~SS_ISSENDING; - error = (*sosp->so_proto->pr_usrreq)(sosp, PRU_SEND, m, NULL, - NULL, NULL); - m = NULL; - if (error) { - if (sosp->so_state & SS_CANTSENDMORE) - error = EPIPE; - goto release; - } - so->so_splicelen += len; + if (so->so_rcv.sb_cc == 0 || maxreached) + sosp->so_state &= ~SS_ISSENDING; + error = (*sosp->so_proto->pr_usrreq)(sosp, PRU_SEND, m, NULL, NULL, + NULL); + if (error) { + if (sosp->so_state & SS_CANTSENDMORE) + error = EPIPE; + goto release; } + so->so_splicelen += len; release: - if (m) - m_freem(m); sosp->so_state &= ~SS_ISSENDING; if (error) so->so_error = error; |