summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2015-07-28 19:59:22 +0000
committerXin LI <delphij@FreeBSD.org>2015-07-28 19:59:22 +0000
commitb768bf90231687be0e762c2e523a20c0e3cd711d (patch)
tree18ed1d227e1c63142d09c88146f25f9d72967e67
parent2e0ab575832c2ee9daa7b2f1a16a14fc5a61a718 (diff)
downloadsrc-test2-b768bf90231687be0e762c2e523a20c0e3cd711d.tar.gz
src-test2-b768bf90231687be0e762c2e523a20c0e3cd711d.zip
Notes
-rw-r--r--UPDATING10
-rw-r--r--contrib/bind9/lib/dns/tkey.c1
-rw-r--r--crypto/openssh/auth2-chall.c10
-rw-r--r--crypto/openssh/sshconnect.c42
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/netinet/tcp_reass.c61
-rw-r--r--sys/netinet/tcp_subr.c4
-rw-r--r--sys/netinet/tcp_var.h5
8 files changed, 73 insertions, 62 deletions
diff --git a/UPDATING b/UPDATING
index c052d1510858..a8ec17af720d 100644
--- a/UPDATING
+++ b/UPDATING
@@ -15,6 +15,16 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW ON IA64 OR SUN4V:
debugging tools present in HEAD were left in place because
sun4v support still needs work to become production ready.
+20150728: p35 FreeBSD-SA-15:15.tcp
+ FreeBSD-SA-15:16.openssh
+ FreeBSD-SA-15:17.bind
+
+ 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]
+
20150721: p34 FreeBSD-SA-15:13.tcp
Fix resource exhaustion due to sessions stuck in LAST_ACK state.
diff --git a/contrib/bind9/lib/dns/tkey.c b/contrib/bind9/lib/dns/tkey.c
index 0112f7ec760e..842931d40453 100644
--- a/contrib/bind9/lib/dns/tkey.c
+++ b/contrib/bind9/lib/dns/tkey.c
@@ -650,6 +650,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
* 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) {
diff --git a/crypto/openssh/auth2-chall.c b/crypto/openssh/auth2-chall.c
index e6dbffe22b91..e5f6d67f5046 100644
--- a/crypto/openssh/auth2-chall.c
+++ b/crypto/openssh/auth2-chall.c
@@ -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 *kbdintctxt)
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);
diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c
index 0076d115a0bf..fa93ce2a4988 100644
--- a/crypto/openssh/sshconnect.c
+++ b/crypto/openssh/sshconnect.c
@@ -1141,29 +1141,39 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
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,
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 086a4bfa5c94..9db505b403bb 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="8.4"
-BRANCH="RELEASE-p34"
+BRANCH="RELEASE-p35"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 4658e0e1f8fc..13254f59784a 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -80,62 +80,49 @@ static int tcp_reass_sysctl_qsize(SYSCTL_HANDLER_ARGS);
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 tcphdr *th, int *tlenp, struct mbuf *m)
*/
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 tcphdr *th, int *tlenp, struct mbuf *m)
* 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 tcphdr *th, int *tlenp, struct mbuf *m)
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 tcphdr *th, int *tlenp, struct mbuf *m)
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);
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index d93093208556..4c1e05b53212 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -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();
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 618250cd0789..d43c1cc68c92 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -653,11 +653,8 @@ char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
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 *);