diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-11-23 17:21:30 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-11-23 17:21:30 +0000 |
commit | 75d5a09a05cfc84f37a727d8c1598a9337b21c70 (patch) | |
tree | 3ce39c4cb642096bc4f16bb881a2f0e32e4e0a8e /sys/netinet | |
parent | 53e97a895b3965eb3ce51576bbbc5b9c4f91d736 (diff) | |
download | FreeBSD-src-75d5a09a05cfc84f37a727d8c1598a9337b21c70.zip FreeBSD-src-75d5a09a05cfc84f37a727d8c1598a9337b21c70.tar.gz |
tcp_timewait() performs multiple non-atomic reads on the tcptw
structure, so assert the inpcb lock associated with the tcptw.
Also assert the tcbinfo lock, as tcp_timewait() may call
tcp_twclose() or tcp_2msl_rest(), which require it. Since
tcp_timewait() is already called with that lock from tcp_input(),
this doesn't change current locking, merely documents reasons for
it.
In tcp_twstart(), assert the tcbinfo lock, as tcp_timer_2msl_rest()
is called, which requires that lock.
In tcp_twclose(), assert the tcbinfo lock, as tcp_timer_2msl_stop()
is called, which requires that lock.
Document the locking strategy for the time wait queues in tcp_timer.c,
which consists of protecting the time wait queues in the same manner
as the tcbinfo structure (using the tcbinfo lock).
In tcp_timer_2msl_reset(), assert the tcbinfo lock, as the time wait
queues are modified.
In tcp_timer_2msl_stop(), assert the tcbinfo lock, as the time wait
queues may be modified.
In tcp_timer_2msl_tw(), assert the tcbinfo lock, as the time wait
queues may be modified.
MFC after: 2 weeks
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp_input.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_timer.c | 9 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 2 |
5 files changed, 21 insertions, 0 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 0a76701..0dc3e89 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -3062,6 +3062,10 @@ tcp_timewait(tw, to, th, m, tlen) const int isipv6 = 0; #endif + /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ + INP_INFO_WLOCK_ASSERT(&tcbinfo); + INP_LOCK_ASSERT(tw->tw_inpcb); + thflags = th->th_flags; /* diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 0a76701..0dc3e89 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -3062,6 +3062,10 @@ tcp_timewait(tw, to, th, m, tlen) const int isipv6 = 0; #endif + /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ + INP_INFO_WLOCK_ASSERT(&tcbinfo); + INP_LOCK_ASSERT(tw->tw_inpcb); + thflags = th->th_flags; /* diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 8064f2b..32044e4 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1624,6 +1624,7 @@ tcp_twstart(tp) int tw_time, acknow; struct socket *so; + INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_reset(). */ INP_LOCK_ASSERT(tp->t_inpcb); tw = uma_zalloc(tcptw_zone, M_NOWAIT); @@ -1722,6 +1723,7 @@ tcp_twclose(struct tcptw *tw, int reuse) struct inpcb *inp; inp = tw->tw_inpcb; + INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_stop(). */ INP_LOCK_ASSERT(inp); tw->tw_inpcb = NULL; diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index d4ae4a9..8fb49eb 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -246,6 +246,12 @@ tcp_timer_2msl(xtp) INP_INFO_WUNLOCK(&tcbinfo); } +/* + * The timed wait lists contain references to each of the TCP sessions + * currently TIME_WAIT state. The list pointers, including the list pointers + * in each tcptw structure, are protected using the global tcbinfo lock, + * which must be held over list iteration and modification. + */ struct twlist { LIST_HEAD(, tcptw) tw_list; struct tcptw tw_tail; @@ -273,6 +279,7 @@ tcp_timer_2msl_reset(struct tcptw *tw, int timeo) int i; struct tcptw *tw_tail; + INP_INFO_WLOCK_ASSERT(&tcbinfo); if (tw->tw_time != 0) LIST_REMOVE(tw, tw_2msl); tw->tw_time = timeo + ticks; @@ -285,6 +292,7 @@ void tcp_timer_2msl_stop(struct tcptw *tw) { + INP_INFO_WLOCK_ASSERT(&tcbinfo); if (tw->tw_time != 0) LIST_REMOVE(tw, tw_2msl); } @@ -296,6 +304,7 @@ tcp_timer_2msl_tw(int reuse) struct twlist *twl; int i; + INP_INFO_WLOCK_ASSERT(&tcbinfo); for (i = 0; i < 2; i++) { twl = tw_2msl_list[i]; tw_tail = &twl->tw_tail; diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 8064f2b..32044e4 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -1624,6 +1624,7 @@ tcp_twstart(tp) int tw_time, acknow; struct socket *so; + INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_reset(). */ INP_LOCK_ASSERT(tp->t_inpcb); tw = uma_zalloc(tcptw_zone, M_NOWAIT); @@ -1722,6 +1723,7 @@ tcp_twclose(struct tcptw *tw, int reuse) struct inpcb *inp; inp = tw->tw_inpcb; + INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_stop(). */ INP_LOCK_ASSERT(inp); tw->tw_inpcb = NULL; |