Date: Tue, 28 Jul 2015 19:58:57 +0000 (UTC) From: Xin LI <delphij@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r285977 - in stable: 8/contrib/bind9/lib/dns 8/crypto/openssh 8/sys/netinet 9/contrib/bind9/lib/dns 9/crypto/openssh 9/sys/netinet Message-ID: <201507281958.t6SJwwI7002565@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Tue Jul 28 19:58:54 2015 New Revision: 285977 URL: https://svnweb.freebsd.org/changeset/base/285977 Log: Fix resource exhaustion in TCP reassembly. [SA-15:15] Fix OpenSSH multiple vulnerabilities. [SA-15:16] Fix BIND remote denial of service vulnerability. [SA-15:17] Modified: stable/8/contrib/bind9/lib/dns/tkey.c stable/8/crypto/openssh/auth2-chall.c stable/8/crypto/openssh/sshconnect.c stable/8/sys/netinet/tcp_reass.c stable/8/sys/netinet/tcp_subr.c stable/8/sys/netinet/tcp_var.h Changes in other areas also in this revision: Modified: stable/9/contrib/bind9/lib/dns/tkey.c stable/9/crypto/openssh/auth2-chall.c stable/9/crypto/openssh/sshconnect.c stable/9/sys/netinet/tcp_reass.c stable/9/sys/netinet/tcp_subr.c stable/9/sys/netinet/tcp_var.h Modified: stable/8/contrib/bind9/lib/dns/tkey.c ============================================================================== --- stable/8/contrib/bind9/lib/dns/tkey.c Tue Jul 28 19:58:44 2015 (r285976) +++ stable/8/contrib/bind9/lib/dns/tkey.c Tue Jul 28 19:58:54 2015 (r285977) @@ -650,6 +650,7 @@ dns_tkey_processquery(dns_message_t *msg * Try the answer section, since that's where Win2000 * puts it. */ + name = NULL; if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_tkey, 0, &name, &tkeyset) != ISC_R_SUCCESS) { Modified: stable/8/crypto/openssh/auth2-chall.c ============================================================================== --- stable/8/crypto/openssh/auth2-chall.c Tue Jul 28 19:58:44 2015 (r285976) +++ stable/8/crypto/openssh/auth2-chall.c Tue Jul 28 19:58:54 2015 (r285977) @@ -82,6 +82,7 @@ struct KbdintAuthctxt void *ctxt; KbdintDevice *device; u_int nreq; + u_int devices_done; }; #ifdef USE_PAM @@ -169,9 +170,14 @@ kbdint_next_device(KbdintAuthctxt *kbdin if (len == 0) break; - for (i = 0; devices[i]; i++) - if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) + for (i = 0; devices[i]; i++) { + if ((kbdintctxt->devices_done & (1 << i)) != 0) + continue; + if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) { kbdintctxt->device = devices[i]; + kbdintctxt->devices_done |= 1 << i; + } + } t = kbdintctxt->devices; kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; xfree(t); Modified: stable/8/crypto/openssh/sshconnect.c ============================================================================== --- stable/8/crypto/openssh/sshconnect.c Tue Jul 28 19:58:44 2015 (r285976) +++ stable/8/crypto/openssh/sshconnect.c Tue Jul 28 19:58:54 2015 (r285977) @@ -1141,29 +1141,39 @@ verify_host_key(char *host, struct socka { int flags = 0; char *fp; + Key *plain = NULL; fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); debug("Server host key: %s %s", key_type(host_key), fp); xfree(fp); - /* XXX certs are not yet supported for DNS */ - if (!key_is_cert(host_key) && options.verify_host_key_dns && - verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) { - if (flags & DNS_VERIFY_FOUND) { - - if (options.verify_host_key_dns == 1 && - flags & DNS_VERIFY_MATCH && - flags & DNS_VERIFY_SECURE) - return 0; - - if (flags & DNS_VERIFY_MATCH) { - matching_host_key_dns = 1; - } else { - warn_changed_key(host_key); - error("Update the SSHFP RR in DNS with the new " - "host key to get rid of this message."); + if (options.verify_host_key_dns) { + /* + * XXX certs are not yet supported for DNS, so downgrade + * them and try the plain key. + */ + plain = key_from_private(host_key); + if (key_is_cert(plain)) + key_drop_cert(plain); + if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { + if (flags & DNS_VERIFY_FOUND) { + if (options.verify_host_key_dns == 1 && + flags & DNS_VERIFY_MATCH && + flags & DNS_VERIFY_SECURE) { + key_free(plain); + return 0; + } + if (flags & DNS_VERIFY_MATCH) { + matching_host_key_dns = 1; + } else { + warn_changed_key(plain); + error("Update the SSHFP RR in DNS " + "with the new host key to get rid " + "of this message."); + } } } + key_free(plain); } return check_host_key(host, hostaddr, options.port, host_key, RDRW, Modified: stable/8/sys/netinet/tcp_reass.c ============================================================================== --- stable/8/sys/netinet/tcp_reass.c Tue Jul 28 19:58:44 2015 (r285976) +++ stable/8/sys/netinet/tcp_reass.c Tue Jul 28 19:58:54 2015 (r285977) @@ -80,62 +80,49 @@ static int tcp_reass_sysctl_qsize(SYSCTL SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0, "TCP Segment Reassembly Queue"); -static VNET_DEFINE(int, tcp_reass_maxseg) = 0; -#define V_tcp_reass_maxseg VNET(tcp_reass_maxseg) +static int tcp_reass_maxseg = 0; SYSCTL_VNET_PROC(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLTYPE_INT | CTLFLAG_RDTUN, - &VNET_NAME(tcp_reass_maxseg), 0, &tcp_reass_sysctl_maxseg, "I", + &tcp_reass_maxseg, 0, &tcp_reass_sysctl_maxseg, "I", "Global maximum number of TCP Segments in Reassembly Queue"); -static VNET_DEFINE(int, tcp_reass_qsize) = 0; -#define V_tcp_reass_qsize VNET(tcp_reass_qsize) -SYSCTL_VNET_PROC(_net_inet_tcp_reass, OID_AUTO, cursegments, +static int tcp_reass_qsize = 0; +SYSCTL_PROC(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLTYPE_INT | CTLFLAG_RD, - &VNET_NAME(tcp_reass_qsize), 0, &tcp_reass_sysctl_qsize, "I", + &tcp_reass_qsize, 0, &tcp_reass_sysctl_qsize, "I", "Global number of TCP Segments currently in Reassembly Queue"); -static VNET_DEFINE(int, tcp_reass_overflows) = 0; -#define V_tcp_reass_overflows VNET(tcp_reass_overflows) -SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows, +static int tcp_reass_overflows = 0; +SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLTYPE_INT | CTLFLAG_RD, - &VNET_NAME(tcp_reass_overflows), 0, + &tcp_reass_overflows, 0, "Global number of TCP Segment Reassembly Queue Overflows"); -static VNET_DEFINE(uma_zone_t, tcp_reass_zone); -#define V_tcp_reass_zone VNET(tcp_reass_zone) +static uma_zone_t tcp_reass_zone; /* Initialize TCP reassembly queue */ static void tcp_reass_zone_change(void *tag) { - V_tcp_reass_maxseg = nmbclusters / 16; - uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg); + tcp_reass_maxseg = nmbclusters / 16; + uma_zone_set_max(tcp_reass_zone, tcp_reass_maxseg); } void -tcp_reass_init(void) +tcp_reass_global_init(void) { - V_tcp_reass_maxseg = nmbclusters / 16; + tcp_reass_maxseg = nmbclusters / 16; TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments", - &V_tcp_reass_maxseg); - V_tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent), + &tcp_reass_maxseg); + tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg); + uma_zone_set_max(tcp_reass_zone, tcp_reass_maxseg); EVENTHANDLER_REGISTER(nmbclusters_change, tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY); } -#ifdef VIMAGE -void -tcp_reass_destroy(void) -{ - - uma_zdestroy(V_tcp_reass_zone); -} -#endif - void tcp_reass_flush(struct tcpcb *tp) { @@ -146,7 +133,7 @@ tcp_reass_flush(struct tcpcb *tp) while ((qe = LIST_FIRST(&tp->t_segq)) != NULL) { LIST_REMOVE(qe, tqe_q); m_freem(qe->tqe_m); - uma_zfree(V_tcp_reass_zone, qe); + uma_zfree(tcp_reass_zone, qe); tp->t_segqlen--; } @@ -158,14 +145,14 @@ tcp_reass_flush(struct tcpcb *tp) static int tcp_reass_sysctl_maxseg(SYSCTL_HANDLER_ARGS) { - V_tcp_reass_maxseg = uma_zone_get_max(V_tcp_reass_zone); + tcp_reass_maxseg = uma_zone_get_max(tcp_reass_zone); return (sysctl_handle_int(oidp, arg1, arg2, req)); } static int tcp_reass_sysctl_qsize(SYSCTL_HANDLER_ARGS) { - V_tcp_reass_qsize = uma_zone_get_cur(V_tcp_reass_zone); + tcp_reass_qsize = uma_zone_get_cur(tcp_reass_zone); return (sysctl_handle_int(oidp, arg1, arg2, req)); } @@ -213,7 +200,7 @@ tcp_reass(struct tcpcb *tp, struct tcphd */ if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) && tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) { - V_tcp_reass_overflows++; + tcp_reass_overflows++; TCPSTAT_INC(tcps_rcvmemdrop); m_freem(m); *tlenp = 0; @@ -232,7 +219,7 @@ tcp_reass(struct tcpcb *tp, struct tcphd * Use a temporary structure on the stack for the missing segment * when the zone is exhausted. Otherwise we may get stuck. */ - te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT); + te = uma_zalloc(tcp_reass_zone, M_NOWAIT); if (te == NULL) { if (th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) { TCPSTAT_INC(tcps_rcvmemdrop); @@ -283,7 +270,7 @@ tcp_reass(struct tcpcb *tp, struct tcphd TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp); m_freem(m); if (te != &tqs) - uma_zfree(V_tcp_reass_zone, te); + uma_zfree(tcp_reass_zone, te); tp->t_segqlen--; /* * Try to present any queued data @@ -320,7 +307,7 @@ tcp_reass(struct tcpcb *tp, struct tcphd nq = LIST_NEXT(q, tqe_q); LIST_REMOVE(q, tqe_q); m_freem(q->tqe_m); - uma_zfree(V_tcp_reass_zone, q); + uma_zfree(tcp_reass_zone, q); tp->t_segqlen--; q = nq; } @@ -359,7 +346,7 @@ present: else sbappendstream_locked(&so->so_rcv, q->tqe_m); if (q != &tqs) - uma_zfree(V_tcp_reass_zone, q); + uma_zfree(tcp_reass_zone, q); tp->t_segqlen--; q = nq; } while (q && q->tqe_th->th_seq == tp->rcv_nxt); Modified: stable/8/sys/netinet/tcp_subr.c ============================================================================== --- stable/8/sys/netinet/tcp_subr.c Tue Jul 28 19:58:44 2015 (r285976) +++ stable/8/sys/netinet/tcp_subr.c Tue Jul 28 19:58:54 2015 (r285977) @@ -375,7 +375,6 @@ tcp_init(void) tcp_tw_init(); syncache_init(); tcp_hc_init(); - tcp_reass_init(); TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack); V_sack_hole_zone = uma_zcreate("sackhole", sizeof(struct sackhole), @@ -385,6 +384,8 @@ tcp_init(void) if (!IS_DEFAULT_VNET(curvnet)) return; + tcp_reass_global_init(); + /* XXX virtualize those bellow? */ tcp_delacktime = TCPTV_DELACK; tcp_keepinit = TCPTV_KEEP_INIT; @@ -424,7 +425,6 @@ void tcp_destroy(void) { - tcp_reass_destroy(); tcp_hc_destroy(); syncache_destroy(); tcp_tw_destroy(); Modified: stable/8/sys/netinet/tcp_var.h ============================================================================== --- stable/8/sys/netinet/tcp_var.h Tue Jul 28 19:58:44 2015 (r285976) +++ stable/8/sys/netinet/tcp_var.h Tue Jul 28 19:58:54 2015 (r285977) @@ -653,11 +653,8 @@ char *tcp_log_addrs(struct in_conninfo char *tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *, const void *); int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *); -void tcp_reass_init(void); +void tcp_reass_global_init(void); void tcp_reass_flush(struct tcpcb *); -#ifdef VIMAGE -void tcp_reass_destroy(void); -#endif void tcp_input(struct mbuf *, int); u_long tcp_maxmtu(struct in_conninfo *, int *); u_long tcp_maxmtu6(struct in_conninfo *, int *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507281958.t6SJwwI7002565>