From cb8d7c44d6acd4f7f6be7f8b762315260f70d896 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Fri, 19 Mar 2021 00:22:36 -0700 Subject: [PATCH] tcp_syncache: add net.inet.tcp.syncache.see_other sysctl A security feature from c06f087ccb12 appeared to be a huge bottleneck under SYN flood. To mitigate that add a sysctl that would make syncache(4) globally visible, ignoring UID/GID, jail(2) and mac(4) checks. When turned on, we won't need to call crhold() on the listening socket credential for every incoming SYN packet. Reviewed by: bz --- share/man/man4/syncache.4 | 29 +++++++++++++++++++++++++++-- sys/netinet/tcp_syncache.c | 10 ++++++++-- sys/netinet/tcp_syncache.h | 1 + 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/share/man/man4/syncache.4 b/share/man/man4/syncache.4 index b212b12cde95..26ed225bcce8 100644 --- a/share/man/man4/syncache.4 +++ b/share/man/man4/syncache.4 @@ -12,7 +12,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 22, 2008 +.Dd April 12, 2021 .Dt SYNCACHE 4 .Os .Sh NAME @@ -39,6 +39,8 @@ MIBs for controlling TCP SYN caching .Nm sysctl Cm net.inet.tcp.syncache.rexmtlimit .It .Nm sysctl Cm net.inet.tcp.syncache.count +.It +.Nm sysctl Cm net.inet.tcp.syncache.see_other .El .Sh DESCRIPTION The @@ -150,6 +152,25 @@ Tunable via Number of entries present in the .Nm (read-only). +.It Va see_other +If set to true value, all +.Nm +entries will be visible via +.Va net.inet.tcp.pcblist +sysctl, or via +.Xr netstat 1 , +ignoring all of +.Xr security 7 +UID/GID, +.Xr jail 2 +and +.Xr mac 4 +checks. +If turned off, the visibility checks are enforced. +However, extra +.Xr ucred 9 +referencing is required on every incoming SYN packet processed. +The default is off. .El .Pp Statistics on the performance of the @@ -192,9 +213,13 @@ Connections created from segment containing ACK. .El .Sh SEE ALSO .Xr netstat 1 , +.Xr jail 2 , +.Xr mac , .Xr tcp 4 , +.Xr security 7, .Xr loader 8 , -.Xr sysctl 8 +.Xr sysctl 8 , +.Xr ucred 9 .Sh HISTORY The existing .Nm diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 7c6bad415d7d..4cd8411af8d5 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -191,6 +191,11 @@ SYSCTL_UINT(_net_inet_tcp_syncache, OID_AUTO, hashsize, CTLFLAG_VNET | CTLFLAG_R &VNET_NAME(tcp_syncache.hashsize), 0, "Size of TCP syncache hashtable"); +SYSCTL_BOOL(_net_inet_tcp_syncache, OID_AUTO, see_other, CTLFLAG_VNET | + CTLFLAG_RW, &VNET_NAME(tcp_syncache.see_other), 0, + "All syncache(4) entries are visible, ignoring UID/GID, jail(2) " + "and mac(4) checks"); + static int sysctl_net_inet_tcp_syncache_rexmtlimit_check(SYSCTL_HANDLER_ARGS) { @@ -1409,7 +1414,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, */ KASSERT(SOLISTENING(so), ("%s: %p not listening", __func__, so)); tp = sototcpcb(so); - cred = crhold(so->so_cred); + cred = V_tcp_syncache.see_other ? NULL : crhold(so->so_cred); #ifdef INET6 if (inc->inc_flags & INC_ISIPV6) { @@ -2498,7 +2503,8 @@ syncache_pcblist(struct sysctl_req *req) sch = &V_tcp_syncache.hashbase[i]; SCH_LOCK(sch); TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { - if (cr_cansee(req->td->td_ucred, sc->sc_cred) != 0) + if (sc->sc_cred != NULL && + cr_cansee(req->td->td_ucred, sc->sc_cred) != 0) continue; if (sc->sc_inc.inc_flags & INC_ISIPV6) xt.xt_inp.inp_vflag = INP_IPV6; diff --git a/sys/netinet/tcp_syncache.h b/sys/netinet/tcp_syncache.h index c56dce55f1c1..03e34a89c112 100644 --- a/sys/netinet/tcp_syncache.h +++ b/sys/netinet/tcp_syncache.h @@ -134,6 +134,7 @@ struct tcp_syncache { time_t pause_until; uint8_t pause_backoff; volatile bool paused; + bool see_other; }; /* Internal use for the syncookie functions. */