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:
parent
8263bab34d
commit
7258e91f0f
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user