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_active(tp->tt_persist))
|
||||||
callout_reset(tp->tt_rexmt, tp->t_rxtcur,
|
callout_reset(tp->tt_rexmt, tp->t_rxtcur,
|
||||||
tcp_timer_rexmt, tp);
|
tcp_timer_rexmt, tp);
|
||||||
tcp_quench(tp->t_inpcb, 0);
|
tp->snd_cwnd = tp->t_maxseg;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
if (error == EMSGSIZE) {
|
if (error == EMSGSIZE) {
|
||||||
|
@ -1117,18 +1117,21 @@ tcp_ctlinput(cmd, sa, vip)
|
|||||||
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
|
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cmd == PRC_QUENCH)
|
if (cmd == PRC_MSGSIZE)
|
||||||
notify = tcp_quench;
|
notify = tcp_mtudisc;
|
||||||
else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
|
else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
|
||||||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
|
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
|
||||||
notify = tcp_drop_syn_sent;
|
notify = tcp_drop_syn_sent;
|
||||||
else if (cmd == PRC_MSGSIZE)
|
|
||||||
notify = tcp_mtudisc;
|
|
||||||
/*
|
/*
|
||||||
* Redirects don't need to be handled up here.
|
* Redirects don't need to be handled up here.
|
||||||
*/
|
*/
|
||||||
else if (PRC_IS_REDIRECT(cmd))
|
else if (PRC_IS_REDIRECT(cmd))
|
||||||
return;
|
return;
|
||||||
|
/*
|
||||||
|
* Source quench is depreciated.
|
||||||
|
*/
|
||||||
|
else if (cmd == PRC_QUENCH)
|
||||||
|
return;
|
||||||
/*
|
/*
|
||||||
* Hostdead is ugly because it goes linearly through all PCBs.
|
* Hostdead is ugly because it goes linearly through all PCBs.
|
||||||
* XXX: We never get this from ICMP, otherwise it makes an
|
* 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))
|
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cmd == PRC_QUENCH)
|
if (cmd == PRC_MSGSIZE)
|
||||||
notify = tcp_quench;
|
|
||||||
else if (cmd == PRC_MSGSIZE)
|
|
||||||
notify = tcp_mtudisc;
|
notify = tcp_mtudisc;
|
||||||
else if (!PRC_IS_REDIRECT(cmd) &&
|
else if (!PRC_IS_REDIRECT(cmd) &&
|
||||||
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
||||||
return;
|
return;
|
||||||
|
/* Source quench is depreciated. */
|
||||||
|
else if (cmd == PRC_QUENCH)
|
||||||
|
return;
|
||||||
|
|
||||||
/* if the parameter is from icmp6, decode it. */
|
/* if the parameter is from icmp6, decode it. */
|
||||||
if (d != NULL) {
|
if (d != NULL) {
|
||||||
@ -1372,23 +1376,6 @@ tcp_isn_tick(xtp)
|
|||||||
INP_INFO_WUNLOCK(&tcbinfo);
|
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
|
* When a specific ICMP unreachable message is received and the
|
||||||
* connection state is SYN-SENT, drop the connection. This behavior
|
* 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)
|
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cmd == PRC_QUENCH)
|
if (cmd == PRC_MSGSIZE)
|
||||||
notify = tcp_quench;
|
notify = tcp_mtudisc;
|
||||||
else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
|
else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
|
||||||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
|
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
|
||||||
notify = tcp_drop_syn_sent;
|
notify = tcp_drop_syn_sent;
|
||||||
else if (cmd == PRC_MSGSIZE)
|
|
||||||
notify = tcp_mtudisc;
|
|
||||||
/*
|
/*
|
||||||
* Redirects don't need to be handled up here.
|
* Redirects don't need to be handled up here.
|
||||||
*/
|
*/
|
||||||
else if (PRC_IS_REDIRECT(cmd))
|
else if (PRC_IS_REDIRECT(cmd))
|
||||||
return;
|
return;
|
||||||
|
/*
|
||||||
|
* Source quench is depreciated.
|
||||||
|
*/
|
||||||
|
else if (cmd == PRC_QUENCH)
|
||||||
|
return;
|
||||||
/*
|
/*
|
||||||
* Hostdead is ugly because it goes linearly through all PCBs.
|
* Hostdead is ugly because it goes linearly through all PCBs.
|
||||||
* XXX: We never get this from ICMP, otherwise it makes an
|
* 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))
|
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cmd == PRC_QUENCH)
|
if (cmd == PRC_MSGSIZE)
|
||||||
notify = tcp_quench;
|
|
||||||
else if (cmd == PRC_MSGSIZE)
|
|
||||||
notify = tcp_mtudisc;
|
notify = tcp_mtudisc;
|
||||||
else if (!PRC_IS_REDIRECT(cmd) &&
|
else if (!PRC_IS_REDIRECT(cmd) &&
|
||||||
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
||||||
return;
|
return;
|
||||||
|
/* Source quench is depreciated. */
|
||||||
|
else if (cmd == PRC_QUENCH)
|
||||||
|
return;
|
||||||
|
|
||||||
/* if the parameter is from icmp6, decode it. */
|
/* if the parameter is from icmp6, decode it. */
|
||||||
if (d != NULL) {
|
if (d != NULL) {
|
||||||
@ -1372,23 +1376,6 @@ tcp_isn_tick(xtp)
|
|||||||
INP_INFO_WUNLOCK(&tcbinfo);
|
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
|
* When a specific ICMP unreachable message is received and the
|
||||||
* connection state is SYN-SENT, drop the connection. This behavior
|
* connection state is SYN-SENT, drop the connection. This behavior
|
||||||
|
@ -534,8 +534,6 @@ struct inpcb *
|
|||||||
struct tcpcb *
|
struct tcpcb *
|
||||||
tcp_newtcpcb(struct inpcb *);
|
tcp_newtcpcb(struct inpcb *);
|
||||||
int tcp_output(struct tcpcb *);
|
int tcp_output(struct tcpcb *);
|
||||||
struct inpcb *
|
|
||||||
tcp_quench(struct inpcb *, int);
|
|
||||||
void tcp_respond(struct tcpcb *, void *,
|
void tcp_respond(struct tcpcb *, void *,
|
||||||
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
|
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
|
||||||
int tcp_twrespond(struct tcptw *, int);
|
int tcp_twrespond(struct tcptw *, int);
|
||||||
|
Loading…
Reference in New Issue
Block a user