o add missing inpcb locking in tcp_respond
o replace spl's with lock assertions Supported by: FreeBSD Foundation
This commit is contained in:
parent
331bf4e6f7
commit
3d0b255a9a
@ -289,13 +289,14 @@ syncache_insert(sc, sch)
|
|||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
{
|
{
|
||||||
struct syncache *sc2;
|
struct syncache *sc2;
|
||||||
int s, i;
|
int i;
|
||||||
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure that we don't overflow the per-bucket
|
* Make sure that we don't overflow the per-bucket
|
||||||
* limit or the total cache size limit.
|
* limit or the total cache size limit.
|
||||||
*/
|
*/
|
||||||
s = splnet();
|
|
||||||
if (sch->sch_length >= tcp_syncache.bucket_limit) {
|
if (sch->sch_length >= tcp_syncache.bucket_limit) {
|
||||||
/*
|
/*
|
||||||
* The bucket is full, toss the oldest element.
|
* The bucket is full, toss the oldest element.
|
||||||
@ -329,7 +330,6 @@ syncache_insert(sc, sch)
|
|||||||
sch->sch_length++;
|
sch->sch_length++;
|
||||||
tcp_syncache.cache_count++;
|
tcp_syncache.cache_count++;
|
||||||
tcpstat.tcps_sc_added++;
|
tcpstat.tcps_sc_added++;
|
||||||
splx(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -337,7 +337,7 @@ syncache_drop(sc, sch)
|
|||||||
struct syncache *sc;
|
struct syncache *sc;
|
||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
{
|
{
|
||||||
int s;
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
if (sch == NULL) {
|
if (sch == NULL) {
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
@ -352,8 +352,6 @@ syncache_drop(sc, sch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s = splnet();
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
||||||
sch->sch_length--;
|
sch->sch_length--;
|
||||||
tcp_syncache.cache_count--;
|
tcp_syncache.cache_count--;
|
||||||
@ -361,7 +359,6 @@ syncache_drop(sc, sch)
|
|||||||
TAILQ_REMOVE(&tcp_syncache.timerq[sc->sc_rxtslot], sc, sc_timerq);
|
TAILQ_REMOVE(&tcp_syncache.timerq[sc->sc_rxtslot], sc, sc_timerq);
|
||||||
if (TAILQ_EMPTY(&tcp_syncache.timerq[sc->sc_rxtslot]))
|
if (TAILQ_EMPTY(&tcp_syncache.timerq[sc->sc_rxtslot]))
|
||||||
callout_stop(&tcp_syncache.tt_timerq[sc->sc_rxtslot]);
|
callout_stop(&tcp_syncache.tt_timerq[sc->sc_rxtslot]);
|
||||||
splx(s);
|
|
||||||
|
|
||||||
syncache_free(sc);
|
syncache_free(sc);
|
||||||
}
|
}
|
||||||
@ -377,14 +374,12 @@ syncache_timer(xslot)
|
|||||||
intptr_t slot = (intptr_t)xslot;
|
intptr_t slot = (intptr_t)xslot;
|
||||||
struct syncache *sc, *nsc;
|
struct syncache *sc, *nsc;
|
||||||
struct inpcb *inp;
|
struct inpcb *inp;
|
||||||
int s;
|
|
||||||
|
|
||||||
s = splnet();
|
|
||||||
INP_INFO_WLOCK(&tcbinfo);
|
INP_INFO_WLOCK(&tcbinfo);
|
||||||
if (callout_pending(&tcp_syncache.tt_timerq[slot]) ||
|
if (callout_pending(&tcp_syncache.tt_timerq[slot]) ||
|
||||||
!callout_active(&tcp_syncache.tt_timerq[slot])) {
|
!callout_active(&tcp_syncache.tt_timerq[slot])) {
|
||||||
INP_INFO_WUNLOCK(&tcbinfo);
|
/* XXX can this happen? */
|
||||||
splx(s);
|
INP_INFO_WLOCK(&tcbinfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callout_deactivate(&tcp_syncache.tt_timerq[slot]);
|
callout_deactivate(&tcp_syncache.tt_timerq[slot]);
|
||||||
@ -421,8 +416,7 @@ syncache_timer(xslot)
|
|||||||
if (nsc != NULL)
|
if (nsc != NULL)
|
||||||
callout_reset(&tcp_syncache.tt_timerq[slot],
|
callout_reset(&tcp_syncache.tt_timerq[slot],
|
||||||
nsc->sc_rxttime - ticks, syncache_timer, (void *)(slot));
|
nsc->sc_rxttime - ticks, syncache_timer, (void *)(slot));
|
||||||
INP_INFO_WUNLOCK(&tcbinfo);
|
INP_INFO_WLOCK(&tcbinfo);
|
||||||
splx(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -435,39 +429,32 @@ syncache_lookup(inc, schp)
|
|||||||
{
|
{
|
||||||
struct syncache *sc;
|
struct syncache *sc;
|
||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
int s;
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
if (inc->inc_isipv6) {
|
if (inc->inc_isipv6) {
|
||||||
sch = &tcp_syncache.hashbase[
|
sch = &tcp_syncache.hashbase[
|
||||||
SYNCACHE_HASH6(inc, tcp_syncache.hashmask)];
|
SYNCACHE_HASH6(inc, tcp_syncache.hashmask)];
|
||||||
*schp = sch;
|
*schp = sch;
|
||||||
s = splnet();
|
|
||||||
TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) {
|
TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) {
|
||||||
if (ENDPTS6_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie)) {
|
if (ENDPTS6_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie))
|
||||||
splx(s);
|
|
||||||
return (sc);
|
return (sc);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
splx(s);
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
sch = &tcp_syncache.hashbase[
|
sch = &tcp_syncache.hashbase[
|
||||||
SYNCACHE_HASH(inc, tcp_syncache.hashmask)];
|
SYNCACHE_HASH(inc, tcp_syncache.hashmask)];
|
||||||
*schp = sch;
|
*schp = sch;
|
||||||
s = splnet();
|
|
||||||
TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) {
|
TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) {
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
if (sc->sc_inc.inc_isipv6)
|
if (sc->sc_inc.inc_isipv6)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
if (ENDPTS_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie)) {
|
if (ENDPTS_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie))
|
||||||
splx(s);
|
|
||||||
return (sc);
|
return (sc);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
splx(s);
|
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -485,6 +472,8 @@ syncache_chkrst(inc, th)
|
|||||||
struct syncache *sc;
|
struct syncache *sc;
|
||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
sc = syncache_lookup(inc, &sch);
|
sc = syncache_lookup(inc, &sch);
|
||||||
if (sc == NULL)
|
if (sc == NULL)
|
||||||
return;
|
return;
|
||||||
@ -515,6 +504,8 @@ syncache_badack(inc)
|
|||||||
struct syncache *sc;
|
struct syncache *sc;
|
||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
sc = syncache_lookup(inc, &sch);
|
sc = syncache_lookup(inc, &sch);
|
||||||
if (sc != NULL) {
|
if (sc != NULL) {
|
||||||
syncache_drop(sc, sch);
|
syncache_drop(sc, sch);
|
||||||
@ -530,6 +521,8 @@ syncache_unreach(inc, th)
|
|||||||
struct syncache *sc;
|
struct syncache *sc;
|
||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
/* we are called at splnet() here */
|
/* we are called at splnet() here */
|
||||||
sc = syncache_lookup(inc, &sch);
|
sc = syncache_lookup(inc, &sch);
|
||||||
if (sc == NULL)
|
if (sc == NULL)
|
||||||
@ -568,6 +561,9 @@ syncache_socket(sc, lso, m)
|
|||||||
struct socket *so;
|
struct socket *so;
|
||||||
struct tcpcb *tp;
|
struct tcpcb *tp;
|
||||||
|
|
||||||
|
GIANT_REQUIRED; /* XXX until socket locking */
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ok, create the full blown connection, and set things up
|
* Ok, create the full blown connection, and set things up
|
||||||
* as they would have been set up if we had created the
|
* as they would have been set up if we had created the
|
||||||
@ -581,13 +577,14 @@ syncache_socket(sc, lso, m)
|
|||||||
* retransmits the ACK,
|
* retransmits the ACK,
|
||||||
*/
|
*/
|
||||||
tcpstat.tcps_listendrop++;
|
tcpstat.tcps_listendrop++;
|
||||||
goto abort;
|
goto abort2;
|
||||||
}
|
}
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
mac_set_socket_peer_from_mbuf(m, so);
|
mac_set_socket_peer_from_mbuf(m, so);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inp = sotoinpcb(so);
|
inp = sotoinpcb(so);
|
||||||
|
INP_LOCK(inp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert new socket into hash list.
|
* Insert new socket into hash list.
|
||||||
@ -745,10 +742,14 @@ syncache_socket(sc, lso, m)
|
|||||||
tp->snd_cwnd = tp->t_maxseg;
|
tp->snd_cwnd = tp->t_maxseg;
|
||||||
callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
|
callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
|
||||||
|
|
||||||
|
INP_UNLOCK(inp);
|
||||||
|
|
||||||
tcpstat.tcps_accepts++;
|
tcpstat.tcps_accepts++;
|
||||||
return (so);
|
return (so);
|
||||||
|
|
||||||
abort:
|
abort:
|
||||||
|
INP_UNLOCK(inp);
|
||||||
|
abort2:
|
||||||
if (so != NULL)
|
if (so != NULL)
|
||||||
(void) soabort(so);
|
(void) soabort(so);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -772,6 +773,8 @@ syncache_expand(inc, th, sop, m)
|
|||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
sc = syncache_lookup(inc, &sch);
|
sc = syncache_lookup(inc, &sch);
|
||||||
if (sc == NULL) {
|
if (sc == NULL) {
|
||||||
/*
|
/*
|
||||||
@ -847,7 +850,9 @@ syncache_add(inc, to, th, sop, m)
|
|||||||
struct syncache_head *sch;
|
struct syncache_head *sch;
|
||||||
struct mbuf *ipopts = NULL;
|
struct mbuf *ipopts = NULL;
|
||||||
struct rmxp_tao *taop;
|
struct rmxp_tao *taop;
|
||||||
int i, s, win;
|
int i, win;
|
||||||
|
|
||||||
|
INP_INFO_WLOCK_ASSERT(&tcbinfo);
|
||||||
|
|
||||||
so = *sop;
|
so = *sop;
|
||||||
tp = sototcpcb(so);
|
tp = sototcpcb(so);
|
||||||
@ -895,11 +900,10 @@ syncache_add(inc, to, th, sop, m)
|
|||||||
#else
|
#else
|
||||||
if (syncache_respond(sc, m) == 0) {
|
if (syncache_respond(sc, m) == 0) {
|
||||||
#endif
|
#endif
|
||||||
s = splnet();
|
/* NB: guarded by INP_INFO_WLOCK(&tcbinfo) */
|
||||||
TAILQ_REMOVE(&tcp_syncache.timerq[sc->sc_rxtslot],
|
TAILQ_REMOVE(&tcp_syncache.timerq[sc->sc_rxtslot],
|
||||||
sc, sc_timerq);
|
sc, sc_timerq);
|
||||||
SYNCACHE_TIMEOUT(sc, sc->sc_rxtslot);
|
SYNCACHE_TIMEOUT(sc, sc->sc_rxtslot);
|
||||||
splx(s);
|
|
||||||
tcpstat.tcps_sndacks++;
|
tcpstat.tcps_sndacks++;
|
||||||
tcpstat.tcps_sndtotal++;
|
tcpstat.tcps_sndtotal++;
|
||||||
}
|
}
|
||||||
@ -914,7 +918,7 @@ syncache_add(inc, to, th, sop, m)
|
|||||||
* Treat this as if the cache was full; drop the oldest
|
* Treat this as if the cache was full; drop the oldest
|
||||||
* entry and insert the new one.
|
* entry and insert the new one.
|
||||||
*/
|
*/
|
||||||
s = splnet();
|
/* NB: guarded by INP_INFO_WLOCK(&tcbinfo) */
|
||||||
for (i = SYNCACHE_MAXREXMTS; i >= 0; i--) {
|
for (i = SYNCACHE_MAXREXMTS; i >= 0; i--) {
|
||||||
sc = TAILQ_FIRST(&tcp_syncache.timerq[i]);
|
sc = TAILQ_FIRST(&tcp_syncache.timerq[i]);
|
||||||
if (sc != NULL)
|
if (sc != NULL)
|
||||||
@ -922,7 +926,6 @@ syncache_add(inc, to, th, sop, m)
|
|||||||
}
|
}
|
||||||
sc->sc_tp->ts_recent = ticks;
|
sc->sc_tp->ts_recent = ticks;
|
||||||
syncache_drop(sc, NULL);
|
syncache_drop(sc, NULL);
|
||||||
splx(s);
|
|
||||||
tcpstat.tcps_sc_zonefail++;
|
tcpstat.tcps_sc_zonefail++;
|
||||||
sc = uma_zalloc(tcp_syncache.zone, M_NOWAIT);
|
sc = uma_zalloc(tcp_syncache.zone, M_NOWAIT);
|
||||||
if (sc == NULL) {
|
if (sc == NULL) {
|
||||||
@ -1086,6 +1089,7 @@ syncache_respond(sc, m)
|
|||||||
struct ip *ip = NULL;
|
struct ip *ip = NULL;
|
||||||
struct rtentry *rt;
|
struct rtentry *rt;
|
||||||
struct tcphdr *th;
|
struct tcphdr *th;
|
||||||
|
struct inpcb *inp;
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
struct ip6_hdr *ip6 = NULL;
|
struct ip6_hdr *ip6 = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -1142,8 +1146,10 @@ syncache_respond(sc, m)
|
|||||||
m->m_len = tlen;
|
m->m_len = tlen;
|
||||||
m->m_pkthdr.len = tlen;
|
m->m_pkthdr.len = tlen;
|
||||||
m->m_pkthdr.rcvif = NULL;
|
m->m_pkthdr.rcvif = NULL;
|
||||||
|
inp = sc->sc_tp->t_inpcb;
|
||||||
|
INP_LOCK(inp);
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
mac_create_mbuf_from_socket(sc->sc_tp->t_inpcb->inp_socket, m);
|
mac_create_mbuf_from_socket(inp->inp_socket, m);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
@ -1171,8 +1177,8 @@ syncache_respond(sc, m)
|
|||||||
ip->ip_p = IPPROTO_TCP;
|
ip->ip_p = IPPROTO_TCP;
|
||||||
ip->ip_src = sc->sc_inc.inc_laddr;
|
ip->ip_src = sc->sc_inc.inc_laddr;
|
||||||
ip->ip_dst = sc->sc_inc.inc_faddr;
|
ip->ip_dst = sc->sc_inc.inc_faddr;
|
||||||
ip->ip_ttl = sc->sc_tp->t_inpcb->inp_ip_ttl; /* XXX */
|
ip->ip_ttl = inp->inp_ip_ttl; /* XXX */
|
||||||
ip->ip_tos = sc->sc_tp->t_inpcb->inp_ip_tos; /* XXX */
|
ip->ip_tos = inp->inp_ip_tos; /* XXX */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we should do MTU discovery. Route lookups are
|
* See if we should do MTU discovery. Route lookups are
|
||||||
@ -1244,8 +1250,7 @@ syncache_respond(sc, m)
|
|||||||
th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen, tlen - hlen);
|
th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen, tlen - hlen);
|
||||||
ip6->ip6_hlim = in6_selecthlim(NULL,
|
ip6->ip6_hlim = in6_selecthlim(NULL,
|
||||||
ro6->ro_rt ? ro6->ro_rt->rt_ifp : NULL);
|
ro6->ro_rt ? ro6->ro_rt->rt_ifp : NULL);
|
||||||
error = ip6_output(m, NULL, ro6, 0, NULL, NULL,
|
error = ip6_output(m, NULL, ro6, 0, NULL, NULL, inp);
|
||||||
sc->sc_tp->t_inpcb);
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -1263,9 +1268,9 @@ syncache_respond(sc, m)
|
|||||||
mtod(m, void *), th, 0);
|
mtod(m, void *), th, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
error = ip_output(m, sc->sc_ipopts, &sc->sc_route, 0, NULL,
|
error = ip_output(m, sc->sc_ipopts, &sc->sc_route, 0, NULL,inp);
|
||||||
sc->sc_tp->t_inpcb);
|
|
||||||
}
|
}
|
||||||
|
INP_UNLOCK(inp);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1332,6 +1337,8 @@ syncookie_generate(struct syncache *sc)
|
|||||||
int idx, i;
|
int idx, i;
|
||||||
struct md5_add add;
|
struct md5_add add;
|
||||||
|
|
||||||
|
/* NB: single threaded; could add INP_INFO_WLOCK_ASSERT(&tcbinfo) */
|
||||||
|
|
||||||
idx = ((ticks << SYNCOOKIE_TIMESHIFT) / hz) & SYNCOOKIE_WNDMASK;
|
idx = ((ticks << SYNCOOKIE_TIMESHIFT) / hz) & SYNCOOKIE_WNDMASK;
|
||||||
if (tcp_secret[idx].ts_expire < ticks) {
|
if (tcp_secret[idx].ts_expire < ticks) {
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
@ -1380,6 +1387,8 @@ syncookie_lookup(inc, th, so)
|
|||||||
int wnd, idx;
|
int wnd, idx;
|
||||||
struct md5_add add;
|
struct md5_add add;
|
||||||
|
|
||||||
|
/* NB: single threaded; could add INP_INFO_WLOCK_ASSERT(&tcbinfo) */
|
||||||
|
|
||||||
data = (th->th_ack - 1) ^ (th->th_seq - 1); /* remove ISS */
|
data = (th->th_ack - 1) ^ (th->th_seq - 1); /* remove ISS */
|
||||||
idx = data & SYNCOOKIE_WNDMASK;
|
idx = data & SYNCOOKIE_WNDMASK;
|
||||||
if (tcp_secret[idx].ts_expire < ticks ||
|
if (tcp_secret[idx].ts_expire < ticks ||
|
||||||
|
Loading…
Reference in New Issue
Block a user