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
This commit is contained in:
Robert Watson 2004-11-23 16:23:13 +00:00
parent 8263bab34d
commit 7258e91f0f
2 changed files with 20 additions and 0 deletions

View File

@ -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);

View File

@ -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);