Skip to content
Permalink
Browse files

Received SACK options are managed by a linked list at the TCP socket.

There is a global tunable limit net.inet.tcp.sackholelimit, default
is 32768.  If an attacker manages to attach all these sack holes
to a few TCP connections, the lists may grow long.  Traversing them
might cause higher CPU consumption on the victim machine.  In
practice such a situation is hard to create as the TCP retransmit
and 2*msl timer flush the list periodically.  For additional
protection, enforce a per connection limit of 128 SACK holes in the
list.
reported by Reuven Plevinsky and Tal Vainshtein
discussed with claudio@ and procter@; OK deraadt@
  • Loading branch information...
bluhm committed Jul 10, 2019
1 parent d038d3d commit ed8fdce754a5d8d14c09e989d8877707bd43906f
Showing with 8 additions and 3 deletions.
  1. +3 −2 sys/netinet/tcp.h
  2. +5 −1 sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
/* $OpenBSD: tcp.h,v 1.20 2013/08/12 21:57:16 bluhm Exp $ */
/* $OpenBSD: tcp.h,v 1.21 2019/07/10 18:45:31 bluhm Exp $ */
/* $NetBSD: tcp.h,v 1.8 1995/04/17 05:32:58 cgd Exp $ */

/*
@@ -102,7 +102,8 @@ struct tcphdr {
#define TCPOPT_SACK_HDR (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_SACK<<8)
/* Miscellaneous constants */
#define MAX_SACK_BLKS 6 /* Max # SACK blocks stored at sender side */
#define TCP_MAX_SACK 3 /* MAX # SACKs sent in any segment */
#define TCP_MAX_SACK 3 /* Max # SACKs sent in any segment */
#define TCP_SACKHOLE_LIMIT 128 /* Max # SACK holes per connection */

#define TCP_MAXBURST 4 /* Max # packets after leaving Fast Rxmit */

@@ -1,4 +1,4 @@
/* $OpenBSD: tcp_input.c,v 1.359 2018/09/17 14:07:48 friehm Exp $ */
/* $OpenBSD: tcp_input.c,v 1.360 2019/07/10 18:45:31 bluhm Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */

/*
@@ -2492,6 +2492,8 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
* ACKs some data in middle of a hole; need to
* split current hole
*/
if (tp->snd_numholes >= TCP_SACKHOLE_LIMIT)
goto done;
temp = (struct sackhole *)
pool_get(&sackhl_pool, PR_NOWAIT);
if (temp == NULL)
@@ -2519,6 +2521,8 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
* Need to append new hole at end.
* Last hole is p (and it's not NULL).
*/
if (tp->snd_numholes >= TCP_SACKHOLE_LIMIT)
goto done;
temp = (struct sackhole *)
pool_get(&sackhl_pool, PR_NOWAIT);
if (temp == NULL)

0 comments on commit ed8fdce

Please sign in to comment.
You can’t perform that action at this time.