diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-11-23 16:23:13 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-11-23 16:23:13 +0000 |
commit | 93fe353ec5725020e33859a4dcde70dd9c0334f3 (patch) | |
tree | b67ae46e3a46c39c67d0c18cfa67d7950a7ab0a6 /sys/netinet | |
parent | 32947f494f39ebc1429459b4beb89f1c642abe0a (diff) | |
download | FreeBSD-src-93fe353ec5725020e33859a4dcde70dd9c0334f3.zip FreeBSD-src-93fe353ec5725020e33859a4dcde70dd9c0334f3.tar.gz |
Assert the inpcb lock in tcp_twstart(), which does both read-modify-write
on the tcpcb, but also calls into tcp_close() and tcp_twrespond().
Annotate that tcp_twrecycleable() requires the inpcb lock because it does
a series of non-atomic reads of the tcpcb, but is currently called
without the inpcb lock by the caller. This is a bug.
Assert the inpcb lock in tcp_twclose() as it performs a read-modify-write
of the timewait structure/inpcb, and calls in_pcbdetach() which requires
the lock.
Assert the inpcb lock in tcp_twrespond(), as it performs multiple
non-atomic reads of the tcptw and inpcb structures, as well as calling
mac_create_mbuf_from_inpcb(), tcpip_fillheaders(), which require the
inpcb lock.
MFC after: 2 weeks
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp_subr.c | 10 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 10 |
2 files changed, 20 insertions, 0 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index e3fcdf1..8064f2b 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1624,6 +1624,8 @@ tcp_twstart(tp) int tw_time, acknow; struct socket *so; + INP_LOCK_ASSERT(tp->t_inpcb); + tw = uma_zalloc(tcptw_zone, M_NOWAIT); if (tw == NULL) { tw = tcp_timer_2msl_tw(1); @@ -1694,6 +1696,10 @@ tcp_twstart(tp) * Determine if the ISN we will generate has advanced beyond the last * sequence number used by the previous connection. If so, indicate * that it is safe to recycle this tw socket by returning 1. + * + * XXXRW: This function should assert the inpcb lock as it does multiple + * non-atomic reads from the tcptw, but is currently * called without it from + * in_pcb.c:in_pcblookup_local(). */ int tcp_twrecycleable(struct tcptw *tw) @@ -1716,6 +1722,8 @@ tcp_twclose(struct tcptw *tw, int reuse) struct inpcb *inp; inp = tw->tw_inpcb; + INP_LOCK_ASSERT(inp); + tw->tw_inpcb = NULL; tcp_timer_2msl_stop(tw); inp->inp_ppcb = NULL; @@ -1749,6 +1757,8 @@ tcp_twrespond(struct tcptw *tw, int flags) int isipv6 = inp->inp_inc.inc_isipv6; #endif + INP_LOCK_ASSERT(inp); + m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m == NULL) return (ENOBUFS); diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index e3fcdf1..8064f2b 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -1624,6 +1624,8 @@ tcp_twstart(tp) int tw_time, acknow; struct socket *so; + INP_LOCK_ASSERT(tp->t_inpcb); + tw = uma_zalloc(tcptw_zone, M_NOWAIT); if (tw == NULL) { tw = tcp_timer_2msl_tw(1); @@ -1694,6 +1696,10 @@ tcp_twstart(tp) * Determine if the ISN we will generate has advanced beyond the last * sequence number used by the previous connection. If so, indicate * that it is safe to recycle this tw socket by returning 1. + * + * XXXRW: This function should assert the inpcb lock as it does multiple + * non-atomic reads from the tcptw, but is currently * called without it from + * in_pcb.c:in_pcblookup_local(). */ int tcp_twrecycleable(struct tcptw *tw) @@ -1716,6 +1722,8 @@ tcp_twclose(struct tcptw *tw, int reuse) struct inpcb *inp; inp = tw->tw_inpcb; + INP_LOCK_ASSERT(inp); + tw->tw_inpcb = NULL; tcp_timer_2msl_stop(tw); inp->inp_ppcb = NULL; @@ -1749,6 +1757,8 @@ tcp_twrespond(struct tcptw *tw, int flags) int isipv6 = inp->inp_inc.inc_isipv6; #endif + INP_LOCK_ASSERT(inp); + m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m == NULL) return (ENOBUFS); |