Resource exhaustion in TCP reassembly.

Corresponding upstream changeset from
https://www.freebsd.org/security/advisories/FreeBSD-SA-18:08.tcp.asc.
dev
fengbojiang(姜凤波) 2019-11-22 16:16:34 +08:00
parent 007a5634b2
commit a98418af32
1 changed files with 11 additions and 1 deletions

View File

@ -89,6 +89,11 @@ SYSCTL_UMA_CUR(_net_inet_tcp_reass, OID_AUTO, cursegments, 0,
&tcp_reass_zone,
"Global number of TCP Segments currently in Reassembly Queue");
static u_int tcp_reass_maxqueuelen = 100;
SYSCTL_UINT(_net_inet_tcp_reass, OID_AUTO, maxqueuelen, CTLFLAG_RWTUN,
&tcp_reass_maxqueuelen, 0,
"Maximum number of TCP Segments per Reassembly Queue");
/* Initialize TCP reassembly queue */
static void
tcp_reass_zone_change(void *tag)
@ -168,6 +173,10 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* socket receive buffer determines our advertised window and grows
* automatically when socket buffer autotuning is enabled. Use it as the
* basis for our queue limit.
*
* However, allow the user to specify a ceiling for the number of
* segments in each queue.
*
* Always let the missing segment through which caused this queue.
* NB: Access to the socket buffer is left intentionally unlocked as we
* can tolerate stale information here.
@ -178,7 +187,8 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* is understood.
*/
if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) {
tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1,
tcp_reass_maxqueuelen)) {
TCPSTAT_INC(tcps_rcvreassfull);
*tlenp = 0;
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {