From 30c2a48ca19a4a28bcd61627066178633f160f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fengbojiang=28=E5=A7=9C=E5=87=A4=E6=B3=A2=29?= Date: Fri, 22 Nov 2019 16:16:34 +0800 Subject: [PATCH] Resource exhaustion in TCP reassembly. Corresponding upstream changeset from https://www.freebsd.org/security/advisories/FreeBSD-SA-18:08.tcp.asc. --- freebsd/netinet/tcp_reass.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/freebsd/netinet/tcp_reass.c b/freebsd/netinet/tcp_reass.c index a22fb3081..c72991f62 100644 --- a/freebsd/netinet/tcp_reass.c +++ b/freebsd/netinet/tcp_reass.c @@ -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))) {