Ignore ICMP Source Quench messages for TCP sessions. Source Quench is
ineffective, depreciated and can be abused to degrade the performance of active TCP sessions if spoofed. Replace a bogus call to tcp_quench() in tcp_output() with the direct equivalent tcpcb variable assignment. Security: draft-gont-tcpm-icmp-attacks-03.txt Section 7.1 MFC after: 3 days
This commit is contained in:
parent
1d968d225f
commit
1600372b6b
@ -1066,7 +1066,7 @@ tcp_output(struct tcpcb *tp)
|
||||
!callout_active(tp->tt_persist))
|
||||
callout_reset(tp->tt_rexmt, tp->t_rxtcur,
|
||||
tcp_timer_rexmt, tp);
|
||||
tcp_quench(tp->t_inpcb, 0);
|
||||
tp->snd_cwnd = tp->t_maxseg;
|
||||
return (0);
|
||||
}
|
||||
if (error == EMSGSIZE) {
|
||||
|
@ -1117,18 +1117,21 @@ tcp_ctlinput(cmd, sa, vip)
|
||||
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
|
||||
return;
|
||||
|
||||
if (cmd == PRC_QUENCH)
|
||||
notify = tcp_quench;
|
||||
if (cmd == PRC_MSGSIZE)
|
||||
notify = tcp_mtudisc;
|
||||
else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
|
||||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
|
||||
notify = tcp_drop_syn_sent;
|
||||
else if (cmd == PRC_MSGSIZE)
|
||||
notify = tcp_mtudisc;
|
||||
/*
|
||||
* Redirects don't need to be handled up here.
|
||||
*/
|
||||
else if (PRC_IS_REDIRECT(cmd))
|
||||
return;
|
||||
/*
|
||||
* Source quench is depreciated.
|
||||
*/
|
||||
else if (cmd == PRC_QUENCH)
|
||||
return;
|
||||
/*
|
||||
* Hostdead is ugly because it goes linearly through all PCBs.
|
||||
* XXX: We never get this from ICMP, otherwise it makes an
|
||||
@ -1197,13 +1200,14 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
return;
|
||||
|
||||
if (cmd == PRC_QUENCH)
|
||||
notify = tcp_quench;
|
||||
else if (cmd == PRC_MSGSIZE)
|
||||
if (cmd == PRC_MSGSIZE)
|
||||
notify = tcp_mtudisc;
|
||||
else if (!PRC_IS_REDIRECT(cmd) &&
|
||||
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
||||
return;
|
||||
/* Source quench is depreciated. */
|
||||
else if (cmd == PRC_QUENCH)
|
||||
return;
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
@ -1372,23 +1376,6 @@ tcp_isn_tick(xtp)
|
||||
INP_INFO_WUNLOCK(&tcbinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a source quench is received, close congestion window
|
||||
* to one segment. We will gradually open it again as we proceed.
|
||||
*/
|
||||
struct inpcb *
|
||||
tcp_quench(inp, errno)
|
||||
struct inpcb *inp;
|
||||
int errno;
|
||||
{
|
||||
struct tcpcb *tp = intotcpcb(inp);
|
||||
|
||||
INP_LOCK_ASSERT(inp);
|
||||
if (tp != NULL)
|
||||
tp->snd_cwnd = tp->t_maxseg;
|
||||
return (inp);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a specific ICMP unreachable message is received and the
|
||||
* connection state is SYN-SENT, drop the connection. This behavior
|
||||
|
@ -1117,18 +1117,21 @@ tcp_ctlinput(cmd, sa, vip)
|
||||
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
|
||||
return;
|
||||
|
||||
if (cmd == PRC_QUENCH)
|
||||
notify = tcp_quench;
|
||||
if (cmd == PRC_MSGSIZE)
|
||||
notify = tcp_mtudisc;
|
||||
else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
|
||||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
|
||||
notify = tcp_drop_syn_sent;
|
||||
else if (cmd == PRC_MSGSIZE)
|
||||
notify = tcp_mtudisc;
|
||||
/*
|
||||
* Redirects don't need to be handled up here.
|
||||
*/
|
||||
else if (PRC_IS_REDIRECT(cmd))
|
||||
return;
|
||||
/*
|
||||
* Source quench is depreciated.
|
||||
*/
|
||||
else if (cmd == PRC_QUENCH)
|
||||
return;
|
||||
/*
|
||||
* Hostdead is ugly because it goes linearly through all PCBs.
|
||||
* XXX: We never get this from ICMP, otherwise it makes an
|
||||
@ -1197,13 +1200,14 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
return;
|
||||
|
||||
if (cmd == PRC_QUENCH)
|
||||
notify = tcp_quench;
|
||||
else if (cmd == PRC_MSGSIZE)
|
||||
if (cmd == PRC_MSGSIZE)
|
||||
notify = tcp_mtudisc;
|
||||
else if (!PRC_IS_REDIRECT(cmd) &&
|
||||
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
||||
return;
|
||||
/* Source quench is depreciated. */
|
||||
else if (cmd == PRC_QUENCH)
|
||||
return;
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
@ -1372,23 +1376,6 @@ tcp_isn_tick(xtp)
|
||||
INP_INFO_WUNLOCK(&tcbinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a source quench is received, close congestion window
|
||||
* to one segment. We will gradually open it again as we proceed.
|
||||
*/
|
||||
struct inpcb *
|
||||
tcp_quench(inp, errno)
|
||||
struct inpcb *inp;
|
||||
int errno;
|
||||
{
|
||||
struct tcpcb *tp = intotcpcb(inp);
|
||||
|
||||
INP_LOCK_ASSERT(inp);
|
||||
if (tp != NULL)
|
||||
tp->snd_cwnd = tp->t_maxseg;
|
||||
return (inp);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a specific ICMP unreachable message is received and the
|
||||
* connection state is SYN-SENT, drop the connection. This behavior
|
||||
|
@ -534,8 +534,6 @@ struct inpcb *
|
||||
struct tcpcb *
|
||||
tcp_newtcpcb(struct inpcb *);
|
||||
int tcp_output(struct tcpcb *);
|
||||
struct inpcb *
|
||||
tcp_quench(struct inpcb *, int);
|
||||
void tcp_respond(struct tcpcb *, void *,
|
||||
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
|
||||
int tcp_twrespond(struct tcptw *, int);
|
||||
|
Loading…
Reference in New Issue
Block a user