From owner-svn-src-stable@freebsd.org Thu May 30 16:32:20 2019 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6A16F15C6C5B; Thu, 30 May 2019 16:32:20 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 0C13E931F2; Thu, 30 May 2019 16:32:20 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id DB7161BB37; Thu, 30 May 2019 16:32:19 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x4UGWJkU066908; Thu, 30 May 2019 16:32:19 GMT (envelope-from tuexen@FreeBSD.org) Received: (from tuexen@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x4UGWJSJ066904; Thu, 30 May 2019 16:32:19 GMT (envelope-from tuexen@FreeBSD.org) Message-Id: <201905301632.x4UGWJSJ066904@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tuexen set sender to tuexen@FreeBSD.org using -f From: Michael Tuexen Date: Thu, 30 May 2019 16:32:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r348435 - stable/11/sys/netinet X-SVN-Group: stable-11 X-SVN-Commit-Author: tuexen X-SVN-Commit-Paths: stable/11/sys/netinet X-SVN-Commit-Revision: 348435 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 0C13E931F2 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.98)[-0.978,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 May 2019 16:32:20 -0000 Author: tuexen Date: Thu May 30 16:32:18 2019 New Revision: 348435 URL: https://svnweb.freebsd.org/changeset/base/348435 Log: MFC r338053: Don't expose the uptime via the TCP timestamps. The TCP client side or the TCP server side when not using SYN-cookies used the uptime as the TCP timestamp value. This patch uses in all cases an offset, which is the result of a keyed hash function taking the source and destination addresses and port numbers into account. The keyed hash function is the same a used for the initial TSN. The use of VNET_DEFINE_STATIC(u_char, ts_offset_secret[32]); had to be replaced by VNET_DEFINE(u_char, ts_offset_secret[32]); MFC r348290: When an ACK segment as the third message of the three way handshake is received and support for time stamps was negotiated in the SYN/SYNACK exchange, perform the PAWS check and only expand the syn cache entry if the check is passed. Without this check, endpoints may get stuck on the incomplete queue. Reviewed by: jtl@, rrs@ Approved by: re (kib@)) Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D16636 Differential Revision: https://reviews.freebsd.org/D20374 Modified: stable/11/sys/netinet/tcp_subr.c stable/11/sys/netinet/tcp_syncache.c stable/11/sys/netinet/tcp_usrreq.c stable/11/sys/netinet/tcp_var.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/netinet/tcp_subr.c ============================================================================== --- stable/11/sys/netinet/tcp_subr.c Thu May 30 16:11:20 2019 (r348434) +++ stable/11/sys/netinet/tcp_subr.c Thu May 30 16:32:18 2019 (r348435) @@ -226,6 +226,12 @@ VNET_DEFINE(uma_zone_t, sack_hole_zone); VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]); +VNET_DEFINE(u_char, ts_offset_secret[32]); +#define V_ts_offset_secret VNET(ts_offset_secret) + +static int tcp_default_fb_init(struct tcpcb *tp); +static void tcp_default_fb_fini(struct tcpcb *tp, int tcb_is_purged); +static int tcp_default_handoff_ok(struct tcpcb *tp); static struct inpcb *tcp_notify(struct inpcb *, int); static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int); static void tcp_mtudisc(struct inpcb *, int); @@ -683,6 +689,7 @@ tcp_init(void) /* Setup the tcp function block list */ init_tcp_functions(); register_tcp_functions(&tcp_def_funcblk, M_WAITOK); + read_random(&V_ts_offset_secret, sizeof(V_ts_offset_secret)); if (tcp_soreceive_stream) { #ifdef INET @@ -2185,7 +2192,41 @@ out: } #endif /* INET6 */ +static uint32_t +tcp_keyed_hash(struct in_conninfo *inc, u_char *key) +{ + MD5_CTX ctx; + uint32_t hash[4]; + MD5Init(&ctx); + MD5Update(&ctx, &inc->inc_fport, sizeof(uint16_t)); + MD5Update(&ctx, &inc->inc_lport, sizeof(uint16_t)); + switch (inc->inc_flags & INC_ISIPV6) { +#ifdef INET + case 0: + MD5Update(&ctx, &inc->inc_faddr, sizeof(struct in_addr)); + MD5Update(&ctx, &inc->inc_laddr, sizeof(struct in_addr)); + break; +#endif +#ifdef INET6 + case INC_ISIPV6: + MD5Update(&ctx, &inc->inc6_faddr, sizeof(struct in6_addr)); + MD5Update(&ctx, &inc->inc6_laddr, sizeof(struct in6_addr)); + break; +#endif + } + MD5Update(&ctx, key, 32); + MD5Final((unsigned char *)hash, &ctx); + + return (hash[0]); +} + +uint32_t +tcp_new_ts_offset(struct in_conninfo *inc) +{ + return (tcp_keyed_hash(inc, V_ts_offset_secret)); +} + /* * Following is where TCP initial sequence number generation occurs. * @@ -2226,7 +2267,7 @@ out: * as reseeding should not be necessary. * * Locking of the global variables isn_secret, isn_last_reseed, isn_offset, - * isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock. In + * isn_offset_old, and isn_ctx is performed using the ISN lock. In * general, this means holding an exclusive (write) lock. */ @@ -2247,15 +2288,11 @@ static VNET_DEFINE(u_int32_t, isn_offset_old); #define V_isn_offset_old VNET(isn_offset_old) tcp_seq -tcp_new_isn(struct tcpcb *tp) +tcp_new_isn(struct in_conninfo *inc) { - MD5_CTX isn_ctx; - u_int32_t md5_buffer[4]; tcp_seq new_isn; u_int32_t projected_offset; - INP_WLOCK_ASSERT(tp->t_inpcb); - ISN_LOCK(); /* Seed if this is the first use, reseed if requested. */ if ((V_isn_last_reseed == 0) || ((V_tcp_isn_reseed_interval > 0) && @@ -2266,26 +2303,7 @@ tcp_new_isn(struct tcpcb *tp) } /* Compute the md5 hash and return the ISN. */ - MD5Init(&isn_ctx); - MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short)); - MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short)); -#ifdef INET6 - if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) { - MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr, - sizeof(struct in6_addr)); - MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr, - sizeof(struct in6_addr)); - } else -#endif - { - MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr, - sizeof(struct in_addr)); - MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr, - sizeof(struct in_addr)); - } - MD5Update(&isn_ctx, (u_char *) &V_isn_secret, sizeof(V_isn_secret)); - MD5Final((u_char *) &md5_buffer, &isn_ctx); - new_isn = (tcp_seq) md5_buffer[0]; + new_isn = (tcp_seq)tcp_keyed_hash(inc, V_isn_secret); V_isn_offset += ISN_STATIC_INCREMENT + (arc4random() & ISN_RANDOM_INCREMENT); if (ticks != V_isn_last) { Modified: stable/11/sys/netinet/tcp_syncache.c ============================================================================== --- stable/11/sys/netinet/tcp_syncache.c Thu May 30 16:11:20 2019 (r348434) +++ stable/11/sys/netinet/tcp_syncache.c Thu May 30 16:32:18 2019 (r348435) @@ -1088,7 +1088,29 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt } } #endif /* TCP_SIGNATURE */ + /* + * RFC 7323 PAWS: If we have a timestamp on this segment and + * it's less than ts_recent, drop it. + * XXXMT: RFC 7323 also requires to send an ACK. + * In tcp_input.c this is only done for TCP segments + * with user data, so be consistent here and just drop + * the segment. + */ + if (sc->sc_flags & SCF_TIMESTAMP && to->to_flags & TOF_TS && + TSTMP_LT(to->to_tsval, sc->sc_tsreflect)) { + SCH_UNLOCK(sch); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) { + log(LOG_DEBUG, + "%s; %s: SEG.TSval %u < TS.Recent %u, " + "segment dropped\n", s, __func__, + to->to_tsval, sc->sc_tsreflect); + free(s, M_TCPLOG); + } + return (-1); /* Do not send RST */ + } + + /* * Pull out the entry to unlock the bucket row. * * NOTE: We must decrease TCPS_SYN_RECEIVED count here, not @@ -1494,6 +1516,7 @@ skip_alloc: if (to->to_flags & TOF_TS) { sc->sc_tsreflect = to->to_tsval; sc->sc_flags |= SCF_TIMESTAMP; + sc->sc_tsoff = tcp_new_ts_offset(inc); } if (to->to_flags & TOF_SCALE) { int wscale = 0; @@ -2029,11 +2052,6 @@ syncookie_generate(struct syncache_head *sch, struct s iss = hash & ~0xff; iss |= cookie.cookie ^ (hash >> 24); - /* Randomize the timestamp. */ - if (sc->sc_flags & SCF_TIMESTAMP) { - sc->sc_tsoff = arc4random() - tcp_ts_getticks(); - } - TCPSTAT_INC(tcps_sc_sendcookie); return (iss); } @@ -2120,7 +2138,7 @@ syncookie_lookup(struct in_conninfo *inc, struct synca if (to->to_flags & TOF_TS) { sc->sc_flags |= SCF_TIMESTAMP; sc->sc_tsreflect = to->to_tsval; - sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks(); + sc->sc_tsoff = tcp_new_ts_offset(inc); } if (to->to_flags & TOF_SIGNATURE) Modified: stable/11/sys/netinet/tcp_usrreq.c ============================================================================== --- stable/11/sys/netinet/tcp_usrreq.c Thu May 30 16:11:20 2019 (r348434) +++ stable/11/sys/netinet/tcp_usrreq.c Thu May 30 16:32:18 2019 (r348435) @@ -1308,7 +1308,9 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, st soisconnecting(so); TCPSTAT_INC(tcps_connattempt); tcp_state_change(tp, TCPS_SYN_SENT); - tp->iss = tcp_new_isn(tp); + tp->iss = tcp_new_isn(&inp->inp_inc); + if (tp->t_flags & TF_REQ_TSTMP) + tp->ts_offset = tcp_new_ts_offset(&inp->inp_inc); tcp_sendseqinit(tp); return 0; @@ -1347,7 +1349,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, s soisconnecting(inp->inp_socket); TCPSTAT_INC(tcps_connattempt); tcp_state_change(tp, TCPS_SYN_SENT); - tp->iss = tcp_new_isn(tp); + tp->iss = tcp_new_isn(&inp->inp_inc); + if (tp->t_flags & TF_REQ_TSTMP) + tp->ts_offset = tcp_new_ts_offset(&inp->inp_inc); tcp_sendseqinit(tp); return 0; Modified: stable/11/sys/netinet/tcp_var.h ============================================================================== --- stable/11/sys/netinet/tcp_var.h Thu May 30 16:11:20 2019 (r348434) +++ stable/11/sys/netinet/tcp_var.h Thu May 30 16:32:18 2019 (r348435) @@ -826,7 +826,9 @@ void tcp_hc_updatemtu(struct in_conninfo *, u_long); void tcp_hc_update(struct in_conninfo *, struct hc_metrics_lite *); extern struct pr_usrreqs tcp_usrreqs; -tcp_seq tcp_new_isn(struct tcpcb *); + +uint32_t tcp_new_ts_offset(struct in_conninfo *); +tcp_seq tcp_new_isn(struct in_conninfo *); int tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq); void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend);