summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-09-23 13:44:42 -0300
committerRenato Botelho <renato@netgate.com>2016-09-23 13:44:42 -0300
commite2276f438816f5c921df6d320a98e6b90a1e613d (patch)
tree79b8811cc54b543a6b62ef758dccc6d9391d5072
parent5a5f882809260c3079797ed53b1a007ca40a0924 (diff)
parenteaf14f8188deb08bcb1fa48ab854b3a3ab8bf939 (diff)
downloadFreeBSD-src-e2276f438816f5c921df6d320a98e6b90a1e613d.zip
FreeBSD-src-e2276f438816f5c921df6d320a98e6b90a1e613d.tar.gz
Merge remote-tracking branch 'origin/releng/10.3' into RELENG_2_3_2
-rw-r--r--UPDATING28
-rw-r--r--crypto/openssl/crypto/bn/bn_print.c9
-rw-r--r--crypto/openssl/crypto/dsa/dsa_ossl.c7
-rw-r--r--crypto/openssl/crypto/mdc2/mdc2dgst.c2
-rw-r--r--crypto/openssl/crypto/ts/ts_lib.c5
-rw-r--r--crypto/openssl/ssl/d1_both.c32
-rw-r--r--crypto/openssl/ssl/d1_clnt.c1
-rw-r--r--crypto/openssl/ssl/d1_lib.c37
-rw-r--r--crypto/openssl/ssl/d1_pkt.c89
-rw-r--r--crypto/openssl/ssl/d1_srvr.c3
-rw-r--r--crypto/openssl/ssl/s3_clnt.c11
-rw-r--r--crypto/openssl/ssl/s3_srvr.c20
-rw-r--r--crypto/openssl/ssl/ssl.h1
-rw-r--r--crypto/openssl/ssl/ssl_err.c4
-rw-r--r--crypto/openssl/ssl/ssl_locl.h3
-rw-r--r--crypto/openssl/ssl/ssl_sess.c2
-rw-r--r--crypto/openssl/ssl/t1_lib.c83
-rw-r--r--sbin/dhclient/dhclient.c21
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c236
-rw-r--r--sys/dev/hyperv/storvsc/hv_vstorage.h5
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel.c24
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c16
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c54
-rw-r--r--sys/dev/hyperv/vmbus/hv_hv.c96
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h15
-rw-r--r--usr.bin/bsdiff/bspatch/bspatch.c4
-rw-r--r--usr.sbin/freebsd-update/freebsd-update.sh2
28 files changed, 567 insertions, 245 deletions
diff --git a/UPDATING b/UPDATING
index 3febf9f..8fc5c51 100644
--- a/UPDATING
+++ b/UPDATING
@@ -16,6 +16,34 @@ from older versions of FreeBSD, try WITHOUT_CLANG to bootstrap to the tip of
stable/10, and then rebuild without this option. The bootstrap process from
older version of current is a bit fragile.
+20160923 p8 FreeBSD-SA-16:26.openssl
+
+ Fix multiple OpenSSL vulnerabilitites.
+
+20160811 p7 FreeBSD-EN-16:10.dhclient
+ FreeBSD-EN-16:11.vmbus
+ FreeBSD-EN-16:12.hv_storvsc
+ FreeBSD-EN-16:13.vmbus
+ FreeBSD-EN-16:14.hv_storvsc
+ FreeBSD-EN-16:15.vmbus
+ FreeBSD-EN-16:16.hv_storvsc
+
+ Fix handling of unknown options from a DHCP server. [EN-16:10]
+ Fix a panic in hv_vmbus(4). [EN-16:11]
+ Fix missing hotplugged disk in hv_storvsc(4). [EN-16:12]
+ Fix the timecounter emulation in hv_vmbus(4). [EN-16:13]
+ Fix callout(9) handling in hv_storvsc(4). [EN-16:14]
+ Fix memory allocation issues in hv_vmbus(4). [EN-16:15]
+ Fix SCSI command handling in hv_storvsc(4). [EN-16:16]
+
+20160725 p6 FreeBSD-SA-16:25.bspatch
+ FreeBSD-EN-16:09.freebsd-update
+
+ Fix bspatch heap overflow vulnerability. [SA-16:25]
+
+ Fix freebsd-update(8) support of FreeBSD 11.0 release
+ distribution. [EN-16:09]
+
20160604 p5 FreeBSD-SA-16:24.ntp
Fix multiple vulnerabilities of ntp.
diff --git a/crypto/openssl/crypto/bn/bn_print.c b/crypto/openssl/crypto/bn/bn_print.c
index bfa31ef..51e4f9e 100644
--- a/crypto/openssl/crypto/bn/bn_print.c
+++ b/crypto/openssl/crypto/bn/bn_print.c
@@ -111,6 +111,7 @@ char *BN_bn2dec(const BIGNUM *a)
char *p;
BIGNUM *t = NULL;
BN_ULONG *bn_data = NULL, *lp;
+ int bn_data_num;
/*-
* get an upper bound for the length of the decimal integer
@@ -120,8 +121,8 @@ char *BN_bn2dec(const BIGNUM *a)
*/
i = BN_num_bits(a) * 3;
num = (i / 10 + i / 1000 + 1) + 1;
- bn_data =
- (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
+ bn_data_num = num / BN_DEC_NUM + 1;
+ bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
buf = (char *)OPENSSL_malloc(num + 3);
if ((buf == NULL) || (bn_data == NULL)) {
BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
@@ -143,7 +144,11 @@ char *BN_bn2dec(const BIGNUM *a)
i = 0;
while (!BN_is_zero(t)) {
*lp = BN_div_word(t, BN_DEC_CONV);
+ if (*lp == (BN_ULONG)-1)
+ goto err;
lp++;
+ if (lp - bn_data >= bn_data_num)
+ goto err;
}
lp--;
/*
diff --git a/crypto/openssl/crypto/dsa/dsa_ossl.c b/crypto/openssl/crypto/dsa/dsa_ossl.c
index 9a3772e..06cd2a2 100644
--- a/crypto/openssl/crypto/dsa/dsa_ossl.c
+++ b/crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -247,11 +247,13 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
do
if (!BN_rand_range(&k, dsa->q))
goto err;
- while (BN_is_zero(&k)) ;
+ while (BN_is_zero(&k));
+
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
BN_set_flags(&k, BN_FLG_CONSTTIME);
}
+
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
CRYPTO_LOCK_DSA, dsa->p, ctx))
@@ -264,6 +266,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
if (!BN_copy(&kq, &k))
goto err;
+ BN_set_flags(&kq, BN_FLG_CONSTTIME);
+
/*
* We do not want timing information to leak the length of k, so we
* compute g^k using an equivalent exponent of fixed length. (This
@@ -282,6 +286,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
} else {
K = &k;
}
+
DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx,
dsa->method_mont_p);
if (!BN_mod(r, r, dsa->q, ctx))
diff --git a/crypto/openssl/crypto/mdc2/mdc2dgst.c b/crypto/openssl/crypto/mdc2/mdc2dgst.c
index 6615cf8..2dce493 100644
--- a/crypto/openssl/crypto/mdc2/mdc2dgst.c
+++ b/crypto/openssl/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@ int MDC2_Update(MDC2_CTX *c, const unsigned char *in, size_t len)
i = c->num;
if (i != 0) {
- if (i + len < MDC2_BLOCK) {
+ if (len < MDC2_BLOCK - i) {
/* partial block */
memcpy(&(c->data[i]), in, len);
c->num += (int)len;
diff --git a/crypto/openssl/crypto/ts/ts_lib.c b/crypto/openssl/crypto/ts/ts_lib.c
index c51538a..e0f1063 100644
--- a/crypto/openssl/crypto/ts/ts_lib.c
+++ b/crypto/openssl/crypto/ts/ts_lib.c
@@ -90,9 +90,8 @@ int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj)
{
char obj_txt[128];
- int len = OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
- BIO_write(bio, obj_txt, len);
- BIO_write(bio, "\n", 1);
+ OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
+ BIO_printf(bio, "%s\n", obj_txt);
return 1;
}
diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c
index aaa1867..30ff7f6 100644
--- a/crypto/openssl/ssl/d1_both.c
+++ b/crypto/openssl/ssl/d1_both.c
@@ -614,11 +614,23 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
int al;
*ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if (item == NULL)
- return 0;
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
- frag = (hm_fragment *)item->data;
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
@@ -1416,18 +1428,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
return ret;
}
-/* call this function when the buffered messages are no longer needed */
-void dtls1_clear_record_buffer(SSL *s)
-{
- pitem *item;
-
- for (item = pqueue_pop(s->d1->sent_messages);
- item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
- dtls1_hm_fragment_free((hm_fragment *)item->data);
- pitem_free(item);
- }
-}
-
unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
unsigned char mt, unsigned long len,
unsigned long frag_off,
diff --git a/crypto/openssl/ssl/d1_clnt.c b/crypto/openssl/ssl/d1_clnt.c
index eb371a2..e1f167b 100644
--- a/crypto/openssl/ssl/d1_clnt.c
+++ b/crypto/openssl/ssl/d1_clnt.c
@@ -751,6 +751,7 @@ int dtls1_connect(SSL *s)
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c
index 011d7b7..99984df 100644
--- a/crypto/openssl/ssl/d1_lib.c
+++ b/crypto/openssl/ssl/d1_lib.c
@@ -144,7 +144,6 @@ int dtls1_new(SSL *s)
static void dtls1_clear_queues(SSL *s)
{
pitem *item = NULL;
- hm_fragment *frag = NULL;
DTLS1_RECORD_DATA *rdata;
while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
@@ -165,28 +164,44 @@ static void dtls1_clear_queues(SSL *s)
pitem_free(item);
}
+ while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ dtls1_clear_received_buffer(s);
+ dtls1_clear_sent_buffer(s);
+}
+
+void dtls1_clear_received_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+
while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
+}
+
+void dtls1_clear_sent_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
-
- while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
- if (rdata->rbuf.buf) {
- OPENSSL_free(rdata->rbuf.buf);
- }
- OPENSSL_free(item->data);
- pitem_free(item);
- }
}
+
void dtls1_free(SSL *s)
{
ssl3_free(s);
@@ -420,7 +435,7 @@ void dtls1_stop_timer(SSL *s)
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
/* Clear retransmission buffer */
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
}
int dtls1_check_timeout_num(SSL *s)
diff --git a/crypto/openssl/ssl/d1_pkt.c b/crypto/openssl/ssl/d1_pkt.c
index d659ed4..008b545 100644
--- a/crypto/openssl/ssl/d1_pkt.c
+++ b/crypto/openssl/ssl/d1_pkt.c
@@ -194,7 +194,7 @@ static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
unsigned char *priority);
-static int dtls1_process_record(SSL *s);
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
@@ -319,21 +319,70 @@ static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
static int dtls1_process_buffered_records(SSL *s)
{
pitem *item;
+ SSL3_BUFFER *rb;
+ SSL3_RECORD *rr;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ int replayok = 1;
item = pqueue_peek(s->d1->unprocessed_rcds.q);
if (item) {
/* Check if epoch is current. */
if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
- return (1); /* Nothing to do. */
+ return 1; /* Nothing to do. */
+
+ rr = &s->s3->rrec;
+ rb = &s->s3->rbuf;
+
+ if (rb->left > 0) {
+ /*
+ * We've still got data from the current packet to read. There could
+ * be a record from the new epoch in it - so don't overwrite it
+ * with the unprocessed records yet (we'll do it when we've
+ * finished reading the current packet).
+ */
+ return 1;
+ }
+
/* Process all the records. */
while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
- if (!dtls1_process_record(s))
- return (0);
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ /*
+ * Should not happen. This will only ever be NULL when the
+ * current record is from a different epoch. But that cannot
+ * be the case because we already checked the epoch above
+ */
+ SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * Check whether this is a repeat, or aged record. We did this
+ * check once already when we first received the record - but
+ * we might have updated the window since then due to
+ * records we subsequently processed.
+ */
+ replayok = dtls1_record_replay_check(s, bitmap);
+ }
+
+ if (!replayok || !dtls1_process_record(s, bitmap)) {
+ /* dump this record */
+ rr->length = 0;
+ s->packet_length = 0;
+ continue;
+ }
+
if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
s->s3->rrec.seq_num) < 0)
- return -1;
+ return 0;
}
}
@@ -344,7 +393,7 @@ static int dtls1_process_buffered_records(SSL *s)
s->d1->processed_rcds.epoch = s->d1->r_epoch;
s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
- return (1);
+ return 1;
}
#if 0
@@ -391,7 +440,7 @@ static int dtls1_get_buffered_record(SSL *s)
#endif
-static int dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i, al;
int enc_err;
@@ -551,6 +600,10 @@ static int dtls1_process_record(SSL *s)
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
return (1);
f_err:
@@ -581,11 +634,12 @@ int dtls1_get_record(SSL *s)
rr = &(s->s3->rrec);
+ again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
- if (dtls1_process_buffered_records(s) < 0)
+ if (!dtls1_process_buffered_records(s))
return -1;
/* if we're renegotiating, then there may be buffered records */
@@ -593,7 +647,6 @@ int dtls1_get_record(SSL *s)
return 1;
/* get something from the wire */
- again:
/* check if we have the header */
if ((s->rstate != SSL_ST_READ_BODY) ||
(s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
@@ -717,20 +770,17 @@ int dtls1_get_record(SSL *s)
if (dtls1_buffer_record
(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
return -1;
- /* Mark receipt of record. */
- dtls1_record_bitmap_update(s, bitmap);
}
rr->length = 0;
s->packet_length = 0;
goto again;
}
- if (!dtls1_process_record(s)) {
+ if (!dtls1_process_record(s, bitmap)) {
rr->length = 0;
s->packet_length = 0; /* dump this record */
goto again; /* get another record */
}
- dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
return (1);
@@ -1814,8 +1864,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
if (rr->epoch == s->d1->r_epoch)
return &s->d1->bitmap;
- /* Only HM and ALERT messages can be from the next epoch */
+ /*
+ * Only HM and ALERT messages can be from the next epoch and only if we
+ * have already processed all of the unprocessed records from the last
+ * epoch
+ */
else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
+ s->d1->unprocessed_rcds.epoch != s->d1->r_epoch &&
(rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
*is_next_epoch = 1;
return &s->d1->next_bitmap;
@@ -1894,6 +1949,12 @@ void dtls1_reset_seq_numbers(SSL *s, int rw)
s->d1->r_epoch++;
memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+
+ /*
+ * We must not use any buffered messages received from the previous
+ * epoch
+ */
+ dtls1_clear_received_buffer(s);
} else {
seq = s->s3->write_sequence;
memcpy(s->d1->last_write_sequence, seq,
diff --git a/crypto/openssl/ssl/d1_srvr.c b/crypto/openssl/ssl/d1_srvr.c
index f01b8a6..af7ae4e 100644
--- a/crypto/openssl/ssl/d1_srvr.c
+++ b/crypto/openssl/ssl/d1_srvr.c
@@ -295,7 +295,7 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown = 0;
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
dtls1_start_timer(s);
ret = dtls1_send_hello_request(s);
if (ret <= 0)
@@ -866,6 +866,7 @@ int dtls1_accept(SSL *s)
/* next message is server hello */
s->d1->handshake_write_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c
index cfa5080..d2ce813 100644
--- a/crypto/openssl/ssl/s3_clnt.c
+++ b/crypto/openssl/ssl/s3_clnt.c
@@ -1143,6 +1143,12 @@ int ssl3_get_server_certificate(SSL *s)
goto f_err;
}
for (nc = 0; nc < llen;) {
+ if (nc + 3 > llen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
n2l3(p, l);
if ((l + nc + 3) > llen) {
al = SSL_AD_DECODE_ERROR;
@@ -2072,6 +2078,11 @@ int ssl3_get_certificate_request(SSL *s)
}
for (nc = 0; nc < llen;) {
+ if (nc + 2 > llen) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG);
+ goto err;
+ }
n2s(p, l);
if ((l + nc + 2) > llen) {
if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c
index 04cf93a..10ff073 100644
--- a/crypto/openssl/ssl/s3_srvr.c
+++ b/crypto/openssl/ssl/s3_srvr.c
@@ -1040,7 +1040,7 @@ int ssl3_get_client_hello(SSL *s)
session_length = *(p + SSL3_RANDOM_SIZE);
- if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ if (SSL3_RANDOM_SIZE + session_length + 1 >= (d + n) - p) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1058,7 +1058,7 @@ int ssl3_get_client_hello(SSL *s)
/* get the session-id */
j = *(p++);
- if (p + j > d + n) {
+ if ((d + n) - p < j) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1114,14 +1114,14 @@ int ssl3_get_client_hello(SSL *s)
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
/* cookie stuff */
- if (p + 1 > d + n) {
+ if ((d + n) - p < 1) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
cookie_len = *(p++);
- if (p + cookie_len > d + n) {
+ if ((d + n ) - p < cookie_len) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1166,7 +1166,7 @@ int ssl3_get_client_hello(SSL *s)
p += cookie_len;
}
- if (p + 2 > d + n) {
+ if ((d + n ) - p < 2) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1180,7 +1180,7 @@ int ssl3_get_client_hello(SSL *s)
}
/* i bytes of cipher data + 1 byte for compression length later */
- if ((p + i + 1) > (d + n)) {
+ if ((d + n) - p < i + 1) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -1246,7 +1246,7 @@ int ssl3_get_client_hello(SSL *s)
/* compression */
i = *(p++);
- if ((p + i) > (d + n)) {
+ if ((d + n) - p < i) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -3237,6 +3237,12 @@ int ssl3_get_client_certificate(SSL *s)
goto f_err;
}
for (nc = 0; nc < llen;) {
+ if (nc + 3 > llen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
n2l3(p, l);
if ((l + nc + 3) > llen) {
al = SSL_AD_DECODE_ERROR;
diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h
index 105047e..d5e8c9a 100644
--- a/crypto/openssl/ssl/ssl.h
+++ b/crypto/openssl/ssl/ssl.h
@@ -2256,6 +2256,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_HEARTBEAT 305
# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
+# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424
# define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
# define SSL_F_DTLS1_PROCESS_RECORD 257
# define SSL_F_DTLS1_READ_BYTES 258
diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c
index caa671a..ed679d1 100644
--- a/crypto/openssl/ssl/ssl_err.c
+++ b/crypto/openssl/ssl/ssl_err.c
@@ -1,6 +1,6 @@
/* ssl/ssl_err.c */
/* ====================================================================
- * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -93,6 +93,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "DTLS1_HEARTBEAT"},
{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"},
{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"},
+ {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS),
+ "DTLS1_PROCESS_BUFFERED_RECORDS"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),
"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h
index f5d9df6..24356e7 100644
--- a/crypto/openssl/ssl/ssl_locl.h
+++ b/crypto/openssl/ssl/ssl_locl.h
@@ -1025,7 +1025,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq,
unsigned long frag_off, int *found);
int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
int dtls1_retransmit_buffered_messages(SSL *s);
-void dtls1_clear_record_buffer(SSL *s);
+void dtls1_clear_received_buffer(SSL *s);
+void dtls1_clear_sent_buffer(SSL *s);
void dtls1_get_message_header(unsigned char *data,
struct hm_header_st *msg_hdr);
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c
index 48fc451..a97d060 100644
--- a/crypto/openssl/ssl/ssl_sess.c
+++ b/crypto/openssl/ssl/ssl_sess.c
@@ -602,7 +602,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
int r;
#endif
- if (session_id + len > limit) {
+ if (limit - session_id < len) {
fatal = 1;
goto err;
}
diff --git a/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c
index 2e9b65b..2c98480 100644
--- a/crypto/openssl/ssl/t1_lib.c
+++ b/crypto/openssl/ssl/t1_lib.c
@@ -942,11 +942,11 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (limit - 2))
+ if (limit - data <= 2)
return;
data += 2;
- if (data > (limit - 4))
+ if (limit - data < 4)
return;
n2s(data, type);
n2s(data, size);
@@ -954,7 +954,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > limit)
+ if (limit - data < size)
return;
data += size;
@@ -962,7 +962,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != limit)
+ if (limit - data != (int)(len1 + len2))
return;
if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
return;
@@ -971,7 +971,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != limit)
+ if (limit - data != (int)(len))
return;
if (memcmp(data, kSafariExtensionsBlock, len) != 0)
return;
@@ -1019,19 +1019,19 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
if (data == limit)
goto ri_check;
- if (data > (limit - 2))
+ if (limit - data < 2)
goto err;
n2s(data, len);
- if (data + len != limit)
+ if (limit - data != len)
goto err;
- while (data <= (limit - 4)) {
+ while (limit - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (limit))
+ if (limit - data < size)
goto err;
# if 0
fprintf(stderr, "Received extension type %d size %d\n", type, size);
@@ -1284,6 +1284,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
size -= 2;
if (dsize > size)
goto err;
+
+ /*
+ * We remove any OCSP_RESPIDs from a previous handshake
+ * to prevent unbounded memory growth - CVE-2016-6304
+ */
+ sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids,
+ OCSP_RESPID_free);
+ if (dsize > 0) {
+ s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
+ if (s->tlsext_ocsp_ids == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else {
+ s->tlsext_ocsp_ids = NULL;
+ }
+
while (dsize > 0) {
OCSP_RESPID *id;
int idsize;
@@ -1303,13 +1320,6 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
OCSP_RESPID_free(id);
goto err;
}
- if (!s->tlsext_ocsp_ids
- && !(s->tlsext_ocsp_ids =
- sk_OCSP_RESPID_new_null())) {
- OCSP_RESPID_free(id);
- *al = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) {
OCSP_RESPID_free(id);
*al = SSL_AD_INTERNAL_ERROR;
@@ -1460,20 +1470,20 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
# endif
- if (data >= (d + n - 2))
+ if ((d + n) - data <= 2)
goto ri_check;
n2s(data, length);
- if (data + length != d + n) {
+ if ((d + n) - data != length) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- while (data <= (d + n - 4)) {
+ while ((d + n) - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (d + n))
+ if ((d + n) - data < size)
goto ri_check;
if (s->tlsext_debug_cb)
@@ -2179,29 +2189,33 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
/* Skip past DTLS cookie */
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
i = *(p++);
- p += i;
- if (p >= limit)
+
+ if (limit - p <= i)
return -1;
+
+ p += i;
}
/* Skip past cipher list */
n2s(p, i);
- p += i;
- if (p >= limit)
+ if (limit - p <= i)
return -1;
+ p += i;
+
/* Skip past compression algorithm list */
i = *(p++);
- p += i;
- if (p > limit)
+ if (limit - p < i)
return -1;
+ p += i;
+
/* Now at start of extensions */
- if ((p + 2) >= limit)
+ if (limit - p <= 2)
return 0;
n2s(p, i);
- while ((p + 4) <= limit) {
+ while (limit - p >= 4) {
unsigned short type, size;
n2s(p, type);
n2s(p, size);
- if (p + size > limit)
+ if (limit - p < size)
return 0;
if (type == TLSEXT_TYPE_session_ticket) {
int r;
@@ -2269,9 +2283,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
HMAC_CTX hctx;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
- /* Need at least keyname + iv + some encrypted data */
- if (eticklen < 48)
- return 2;
+
/* Initialize session ticket encryption and HMAC contexts */
HMAC_CTX_init(&hctx);
EVP_CIPHER_CTX_init(&ctx);
@@ -2305,6 +2317,13 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
if (mlen < 0) {
goto err;
}
+ /* Sanity check ticket length: must exceed keyname + IV + HMAC */
+ if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) {
+ HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return 2;
+ }
+
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
if (HMAC_Update(&hctx, etick, eticklen) <= 0
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 97f9d47..b173eb2 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -2277,6 +2277,17 @@ script_set_env(struct client_state *client, const char *prefix,
{
int i, j, namelen;
+ /* No `` or $() command substitution allowed in environment values! */
+ for (j=0; j < strlen(value); j++)
+ switch (value[j]) {
+ case '`':
+ case '$':
+ warning("illegal character (%c) in value '%s'",
+ value[j], value);
+ /* Ignore this option */
+ return;
+ }
+
namelen = strlen(name);
for (i = 0; client->scriptEnv[i]; i++)
@@ -2313,16 +2324,6 @@ script_set_env(struct client_state *client, const char *prefix,
strlen(value) + 1);
if (client->scriptEnv[i] == NULL)
error("script_set_env: no memory for variable assignment");
-
- /* No `` or $() command substitution allowed in environment values! */
- for (j=0; j < strlen(value); j++)
- switch (value[j]) {
- case '`':
- case '$':
- error("illegal character (%c) in value '%s'", value[j],
- value);
- /* not reached */
- }
snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
}
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index b0022a6..8b54e44 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="10.3"
-BRANCH="RELEASE-p5"
+BRANCH="RELEASE-p8"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
index 7582aec..0a750d9 100644
--- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -81,12 +81,6 @@ __FBSDID("$FreeBSD$");
#define BLKVSC_MAX_IO_REQUESTS STORVSC_MAX_IO_REQUESTS
#define STORVSC_MAX_TARGETS (2)
-#define STORVSC_WIN7_MAJOR 4
-#define STORVSC_WIN7_MINOR 2
-
-#define STORVSC_WIN8_MAJOR 5
-#define STORVSC_WIN8_MINOR 1
-
#define VSTOR_PKT_SIZE (sizeof(struct vstor_packet) - vmscsi_size_delta)
#define HV_ALIGN(x, a) roundup2(x, a)
@@ -208,7 +202,7 @@ static struct storvsc_driver_props g_drv_props_table[] = {
* Sense buffer size changed in win8; have a run-time
* variable to track the size we should use.
*/
-static int sense_buffer_size;
+static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
/*
* The size of the vmscsi_request has changed in win8. The
@@ -218,9 +212,46 @@ static int sense_buffer_size;
* Track the correct size we need to apply.
*/
static int vmscsi_size_delta;
+/*
+ * The storage protocol version is determined during the
+ * initial exchange with the host. It will indicate which
+ * storage functionality is available in the host.
+*/
+static int vmstor_proto_version;
+
+struct vmstor_proto {
+ int proto_version;
+ int sense_buffer_size;
+ int vmscsi_size_delta;
+};
-static int storvsc_current_major;
-static int storvsc_current_minor;
+static const struct vmstor_proto vmstor_proto_list[] = {
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN10,
+ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
+ 0
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN8_1,
+ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
+ 0
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN8,
+ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
+ 0
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN7,
+ PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
+ sizeof(struct vmscsi_win8_extension),
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN6,
+ PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
+ sizeof(struct vmscsi_win8_extension),
+ }
+};
/* static functions */
static int storvsc_probe(device_t dev);
@@ -435,7 +466,7 @@ storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
static int
hv_storvsc_channel_init(struct hv_device *dev)
{
- int ret = 0;
+ int ret = 0, i;
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
struct storvsc_softc *sc;
@@ -484,19 +515,20 @@ hv_storvsc_channel_init(struct hv_device *dev)
goto cleanup;
}
- /* reuse the packet for version range supported */
+ for (i = 0; i < nitems(vmstor_proto_list); i++) {
+ /* reuse the packet for version range supported */
- memset(vstor_packet, 0, sizeof(struct vstor_packet));
- vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION;
- vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+ memset(vstor_packet, 0, sizeof(struct vstor_packet));
+ vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION;
+ vstor_packet->flags = REQUEST_COMPLETION_FLAG;
- vstor_packet->u.version.major_minor =
- VMSTOR_PROTOCOL_VERSION(storvsc_current_major, storvsc_current_minor);
+ vstor_packet->u.version.major_minor =
+ vmstor_proto_list[i].proto_version;
- /* revision is only significant for Windows guests */
- vstor_packet->u.version.revision = 0;
+ /* revision is only significant for Windows guests */
+ vstor_packet->u.version.revision = 0;
- ret = hv_vmbus_channel_send_packet(
+ ret = hv_vmbus_channel_send_packet(
dev->channel,
vstor_packet,
VSTOR_PKT_SIZE,
@@ -504,20 +536,34 @@ hv_storvsc_channel_init(struct hv_device *dev)
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
- if (ret != 0)
- goto cleanup;
+ if (ret != 0)
+ goto cleanup;
- /* wait 5 seconds */
- ret = sema_timedwait(&request->synch_sema, 5 * hz);
+ /* wait 5 seconds */
+ ret = sema_timedwait(&request->synch_sema, 5 * hz);
- if (ret)
- goto cleanup;
+ if (ret)
+ goto cleanup;
- /* TODO: Check returned version */
- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO ||
- vstor_packet->status != 0)
- goto cleanup;
+ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO) {
+ ret = EINVAL;
+ goto cleanup;
+ }
+ if (vstor_packet->status == 0) {
+ vmstor_proto_version =
+ vmstor_proto_list[i].proto_version;
+ sense_buffer_size =
+ vmstor_proto_list[i].sense_buffer_size;
+ vmscsi_size_delta =
+ vmstor_proto_list[i].vmscsi_size_delta;
+ break;
+ }
+ }
+ if (vstor_packet->status != 0) {
+ ret = EINVAL;
+ goto cleanup;
+ }
/**
* Query channel properties
*/
@@ -767,6 +813,13 @@ hv_storvsc_on_iocompletion(struct storvsc_softc *sc,
vm_srb = &vstor_packet->u.vm_srb;
+ /*
+ * Copy some fields of the host's response into the request structure,
+ * because the fields will be used later in storvsc_io_done().
+ */
+ request->vstor_packet.u.vm_srb.scsi_status = vm_srb->scsi_status;
+ request->vstor_packet.u.vm_srb.transfer_len = vm_srb->transfer_len;
+
if (((vm_srb->scsi_status & 0xFF) == SCSI_STATUS_CHECK_COND) &&
(vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)) {
/* Autosense data available */
@@ -916,19 +969,6 @@ storvsc_probe(device_t dev)
int ata_disk_enable = 0;
int ret = ENXIO;
- if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 ||
- hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) {
- sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
- vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
- storvsc_current_major = STORVSC_WIN7_MAJOR;
- storvsc_current_minor = STORVSC_WIN7_MINOR;
- } else {
- sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
- vmscsi_size_delta = 0;
- storvsc_current_major = STORVSC_WIN8_MAJOR;
- storvsc_current_minor = STORVSC_WIN8_MINOR;
- }
-
switch (storvsc_get_storage_type(dev)) {
case DRIVER_BLKVSC:
if(bootverbose)
@@ -1273,6 +1313,7 @@ storvsc_timeout_test(struct hv_storvsc_request *reqp,
}
#endif /* HVS_TIMEOUT_TEST */
+#ifdef notyet
/**
* @brief timeout handler for requests
*
@@ -1320,6 +1361,7 @@ storvsc_timeout(void *arg)
storvsc_timeout_test(reqp, MODE_SELECT_10, 1);
#endif
}
+#endif
/**
* @brief StorVSC device poll function
@@ -1472,6 +1514,7 @@ storvsc_action(struct cam_sim *sim, union ccb *ccb)
return;
}
+#ifdef notyet
if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
callout_init(&reqp->callout, CALLOUT_MPSAFE);
callout_reset_sbt(&reqp->callout,
@@ -1491,6 +1534,7 @@ storvsc_action(struct cam_sim *sim, union ccb *ccb)
}
#endif /* HVS_TIMEOUT_TEST */
}
+#endif
if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) {
xpt_print(ccb->ccb_h.path,
@@ -1924,62 +1968,24 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp)
}
/*
- * Modified based on scsi_print_inquiry which is responsible to
- * print the detail information for scsi_inquiry_data.
- *
+ * SCSI Inquiry checks qualifier and type.
+ * If qualifier is 011b, means the device server is not capable
+ * of supporting a peripheral device on this logical unit, and
+ * the type should be set to 1Fh.
+ *
* Return 1 if it is valid, 0 otherwise.
*/
static inline int
is_inquiry_valid(const struct scsi_inquiry_data *inq_data)
{
uint8_t type;
- char vendor[16], product[48], revision[16];
-
- /*
- * Check device type and qualifier
- */
- if (!(SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ||
- SID_QUAL(inq_data) == SID_QUAL_LU_CONNECTED))
+ if (SID_QUAL(inq_data) != SID_QUAL_LU_CONNECTED) {
return (0);
-
+ }
type = SID_TYPE(inq_data);
- switch (type) {
- case T_DIRECT:
- case T_SEQUENTIAL:
- case T_PRINTER:
- case T_PROCESSOR:
- case T_WORM:
- case T_CDROM:
- case T_SCANNER:
- case T_OPTICAL:
- case T_CHANGER:
- case T_COMM:
- case T_STORARRAY:
- case T_ENCLOSURE:
- case T_RBC:
- case T_OCRW:
- case T_OSD:
- case T_ADC:
- break;
- case T_NODEVICE:
- default:
+ if (type == T_NODEVICE) {
return (0);
}
-
- /*
- * Check vendor, product, and revision
- */
- cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
- sizeof(vendor));
- cam_strvis(product, inq_data->product, sizeof(inq_data->product),
- sizeof(product));
- cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
- sizeof(revision));
- if (strlen(vendor) == 0 ||
- strlen(product) == 0 ||
- strlen(revision) == 0)
- return (0);
-
return (1);
}
@@ -2039,6 +2045,7 @@ storvsc_io_done(struct hv_storvsc_request *reqp)
mtx_unlock(&sc->hs_lock);
}
+#ifdef notyet
/*
* callout_drain() will wait for the timer handler to finish
* if it is running. So we don't need any lock to synchronize
@@ -2049,12 +2056,12 @@ storvsc_io_done(struct hv_storvsc_request *reqp)
if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
callout_drain(&reqp->callout);
}
+#endif
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
if (vm_srb->scsi_status == SCSI_STATUS_OK) {
const struct scsi_generic *cmd;
-
/*
* Check whether the data for INQUIRY cmd is valid or
* not. Windows 10 and Windows 2016 send all zero
@@ -2063,16 +2070,59 @@ storvsc_io_done(struct hv_storvsc_request *reqp)
cmd = (const struct scsi_generic *)
((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
- if (cmd->opcode == INQUIRY &&
- is_inquiry_valid(
- (const struct scsi_inquiry_data *)csio->data_ptr) == 0) {
+ if (cmd->opcode == INQUIRY) {
+ /*
+ * The host of Windows 10 or 2016 server will response
+ * the inquiry request with invalid data for unexisted device:
+ [0x7f 0x0 0x5 0x2 0x1f ... ]
+ * But on windows 2012 R2, the response is:
+ [0x7f 0x0 0x0 0x0 0x0 ]
+ * That is why here wants to validate the inquiry response.
+ * The validation will skip the INQUIRY whose response is short,
+ * which is less than SHORT_INQUIRY_LENGTH (36).
+ *
+ * For more information about INQUIRY, please refer to:
+ * ftp://ftp.avc-pioneer.com/Mtfuji_7/Proposal/Jun09/INQUIRY.pdf
+ */
+ const struct scsi_inquiry_data *inq_data =
+ (const struct scsi_inquiry_data *)csio->data_ptr;
+ uint8_t* resp_buf = (uint8_t*)csio->data_ptr;
+ /* Get the buffer length reported by host */
+ int resp_xfer_len = vm_srb->transfer_len;
+ /* Get the available buffer length */
+ int resp_buf_len = resp_xfer_len >= 5 ? resp_buf[4] + 5 : 0;
+ int data_len = (resp_buf_len < resp_xfer_len) ? resp_buf_len : resp_xfer_len;
+ if (data_len < SHORT_INQUIRY_LENGTH) {
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ if (bootverbose && data_len >= 5) {
+ mtx_lock(&sc->hs_lock);
+ xpt_print(ccb->ccb_h.path,
+ "storvsc skips the validation for short inquiry (%d)"
+ " [%x %x %x %x %x]\n",
+ data_len,resp_buf[0],resp_buf[1],resp_buf[2],
+ resp_buf[3],resp_buf[4]);
+ mtx_unlock(&sc->hs_lock);
+ }
+ } else if (is_inquiry_valid(inq_data) == 0) {
ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ if (bootverbose && data_len >= 5) {
+ mtx_lock(&sc->hs_lock);
+ xpt_print(ccb->ccb_h.path,
+ "storvsc uninstalled invalid device"
+ " [%x %x %x %x %x]\n",
+ resp_buf[0],resp_buf[1],resp_buf[2],resp_buf[3],resp_buf[4]);
+ mtx_unlock(&sc->hs_lock);
+ }
+ } else {
+ ccb->ccb_h.status |= CAM_REQ_CMP;
if (bootverbose) {
mtx_lock(&sc->hs_lock);
xpt_print(ccb->ccb_h.path,
- "storvsc uninstalled device\n");
+ "storvsc has passed inquiry response (%d) validation\n",
+ data_len);
mtx_unlock(&sc->hs_lock);
}
+ }
} else {
ccb->ccb_h.status |= CAM_REQ_CMP;
}
diff --git a/sys/dev/hyperv/storvsc/hv_vstorage.h b/sys/dev/hyperv/storvsc/hv_vstorage.h
index 026189c..f2b9480 100644
--- a/sys/dev/hyperv/storvsc/hv_vstorage.h
+++ b/sys/dev/hyperv/storvsc/hv_vstorage.h
@@ -41,6 +41,11 @@
#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
(((MINOR_) & 0xff) ))
+#define VMSTOR_PROTOCOL_VERSION_WIN6 VMSTOR_PROTOCOL_VERSION(2, 0)
+#define VMSTOR_PROTOCOL_VERSION_WIN7 VMSTOR_PROTOCOL_VERSION(4, 2)
+#define VMSTOR_PROTOCOL_VERSION_WIN8 VMSTOR_PROTOCOL_VERSION(5, 1)
+#define VMSTOR_PROTOCOL_VERSION_WIN8_1 VMSTOR_PROTOCOL_VERSION(6, 0)
+#define VMSTOR_PROTOCOL_VERSION_WIN10 VMSTOR_PROTOCOL_VERSION(6, 2)
/*
* Invalid version.
*/
diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c
index 7037768..c144910 100644
--- a/sys/dev/hyperv/vmbus/hv_channel.c
+++ b/sys/dev/hyperv/vmbus/hv_channel.c
@@ -180,12 +180,12 @@ hv_vmbus_channel_open(
if (user_data_len)
memcpy(open_msg->user_data, user_data, user_data_len);
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(
&hv_vmbus_g_connection.channel_msg_anchor,
open_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(
open_msg, sizeof(hv_vmbus_channel_open_channel));
@@ -212,12 +212,12 @@ hv_vmbus_channel_open(
}
cleanup:
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(
&hv_vmbus_g_connection.channel_msg_anchor,
open_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
sema_destroy(&open_info->wait_sema);
free(open_info, M_DEVBUF);
@@ -401,13 +401,13 @@ hv_vmbus_channel_establish_gpadl(
gpadl_msg->child_rel_id = channel->offer_msg.child_rel_id;
gpadl_msg->gpadl = next_gpadl_handle;
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(
gpadl_msg,
@@ -446,10 +446,10 @@ hv_vmbus_channel_establish_gpadl(
cleanup:
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
msg_info, msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
sema_destroy(&msg_info->wait_sema);
free(msg_info, M_DEVBUF);
@@ -488,10 +488,10 @@ hv_vmbus_channel_teardown_gpdal(
msg->child_rel_id = channel->offer_msg.child_rel_id;
msg->gpadl = gpadl_handle;
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_msg_anchor,
info, msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(msg,
sizeof(hv_vmbus_channel_gpadl_teardown));
@@ -504,10 +504,10 @@ cleanup:
/*
* Received a torndown response
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
info, msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
sema_destroy(&info->wait_sema);
free(info, M_DEVBUF);
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index 4ccb647..a55f464 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -567,7 +567,7 @@ vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr)
/*
* Find the open msg, copy the result and signal/unblock the wait event
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
@@ -585,7 +585,7 @@ vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr)
}
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
@@ -609,7 +609,7 @@ vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr)
/* Find the establish msg, copy the result and signal/unblock
* the wait event
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
request_header = (hv_vmbus_channel_msg_header*) msg_info->msg;
@@ -628,7 +628,7 @@ vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr)
}
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
/**
@@ -653,7 +653,7 @@ vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr)
* wait event.
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
@@ -673,7 +673,7 @@ vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr)
}
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
/**
@@ -693,7 +693,7 @@ vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr)
versionResponse = (hv_vmbus_channel_version_response*)hdr;
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
requestHeader = (hv_vmbus_channel_msg_header*) msg_info->msg;
@@ -707,7 +707,7 @@ vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr)
sema_post(&msg_info->wait_sema);
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index cfdc9bb..f39616f 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -101,26 +101,26 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
* Add to list before we send the request since we may receive the
* response before returning from this routine
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(
msg,
sizeof(hv_vmbus_channel_initiate_contact));
if (ret != 0) {
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
return (ret);
}
@@ -129,12 +129,12 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
*/
ret = sema_timedwait(&msg_info->wait_sema, 5 * hz); /* KYS 5 seconds */
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
/**
* Check if successful
@@ -173,7 +173,7 @@ hv_vmbus_connect(void) {
TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor);
mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg",
- NULL, MTX_SPIN);
+ NULL, MTX_DEF);
TAILQ_INIT(&hv_vmbus_g_connection.channel_anchor);
mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel",
@@ -476,31 +476,35 @@ hv_vmbus_on_events(void *arg)
/**
* Send a msg on the vmbus's message connection
*/
-int hv_vmbus_post_message(void *buffer, size_t bufferLen) {
- int ret = 0;
+int hv_vmbus_post_message(void *buffer, size_t bufferLen)
+{
hv_vmbus_connection_id connId;
- unsigned retries = 0;
+ sbintime_t time = SBT_1MS;
+ int retries;
+ int ret;
- /* NetScaler delays from previous code were consolidated here */
- static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
+ connId.as_uint32_t = 0;
+ connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- /* for(each entry in delayAmount) try to post message,
- * delay a little bit before retrying
+ /*
+ * We retry to cope with transient failures caused by host side's
+ * insufficient resources. 20 times should suffice in practice.
*/
- for (retries = 0;
- retries < sizeof(delayAmount)/sizeof(delayAmount[0]); retries++) {
- connId.as_uint32_t = 0;
- connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, bufferLen);
- if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
- break;
- /* TODO: KYS We should use a blocking wait call */
- DELAY(delayAmount[retries]);
+ for (retries = 0; retries < 20; retries++) {
+ ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer,
+ bufferLen);
+ if (ret == HV_STATUS_SUCCESS)
+ return (0);
+
+ pause_sbt("pstmsg", time, 0, C_HARDCLOCK);
+ if (time < SBT_1S * 2)
+ time *= 2;
}
- KASSERT(ret == 0, ("Error VMBUS: Message Post Failed\n"));
+ KASSERT(ret == HV_STATUS_SUCCESS,
+ ("Error VMBUS: Message Post Failed, ret=%d\n", ret));
- return (ret);
+ return (EAGAIN);
}
/**
diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c
index ca5641f..f4cca18 100644
--- a/sys/dev/hyperv/vmbus/hv_hv.c
+++ b/sys/dev/hyperv/vmbus/hv_hv.c
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/timetc.h>
@@ -50,6 +51,9 @@ __FBSDID("$FreeBSD$");
static u_int hv_get_timecount(struct timecounter *tc);
+u_int hyperv_features;
+u_int hyperv_recommends;
+
/**
* Globals
*/
@@ -211,8 +215,6 @@ hv_vmbus_init(void)
hv_vmbus_g_context.hypercall_page = virt_addr;
- tc_init(&hv_timecounter); /* register virtual timecount */
-
hv_et_init();
return (0);
@@ -427,3 +429,93 @@ void hv_vmbus_synic_cleanup(void *arg)
wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
}
+static bool
+hyperv_identify(void)
+{
+ u_int regs[4];
+ unsigned int maxLeaf;
+ unsigned int op;
+
+ if (vm_guest != VM_GUEST_HV)
+ return (false);
+
+ op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
+ do_cpuid(op, regs);
+ maxLeaf = regs[0];
+ if (maxLeaf < HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS)
+ return (false);
+
+ op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
+ do_cpuid(op, regs);
+ if (regs[0] != 0x31237648 /* HV#1 */)
+ return (false);
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_FEATURES;
+ do_cpuid(op, regs);
+ if ((regs[0] & HV_FEATURE_MSR_HYPERCALL) == 0) {
+ /*
+ * Hyper-V w/o Hypercall is impossible; someone
+ * is faking Hyper-V.
+ */
+ return (false);
+ }
+ hyperv_features = regs[0];
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
+ do_cpuid(op, regs);
+ printf("Hyper-V Version: %d.%d.%d [SP%d]\n",
+ regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]);
+
+ printf(" Features: 0x%b\n", hyperv_features,
+ "\020"
+ "\001VPRUNTIME"
+ "\002TMREFCNT"
+ "\003SYNCIC"
+ "\004SYNCTM"
+ "\005APIC"
+ "\006HYERCALL"
+ "\007VPINDEX"
+ "\010RESET"
+ "\011STATS"
+ "\012REFTSC"
+ "\013IDLE"
+ "\014TMFREQ"
+ "\015DEBUG");
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION;
+ do_cpuid(op, regs);
+ hyperv_recommends = regs[0];
+ if (bootverbose)
+ printf(" Recommends: %08x %08x\n", regs[0], regs[1]);
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS;
+ do_cpuid(op, regs);
+ if (bootverbose) {
+ printf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n",
+ regs[0], regs[1], regs[2]);
+ }
+
+ if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE) {
+ op = HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE;
+ do_cpuid(op, regs);
+ if (bootverbose) {
+ printf(" HW Features: %08x AMD: %08x\n",
+ regs[0], regs[3]);
+ }
+ }
+
+ return (true);
+}
+
+static void
+hyperv_init(void *dummy __unused)
+{
+ if (!hyperv_identify())
+ return;
+
+ if (hyperv_features & HV_FEATURE_MSR_TIME_REFCNT) {
+ /* Register virtual timecount */
+ tc_init(&hv_timecounter);
+ }
+}
+SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init, NULL);
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 13a35c4..bf103ab 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -70,6 +70,7 @@ typedef uint16_t hv_vmbus_status;
* You did not supply enough message buffers to send a message.
*/
+#define HV_STATUS_SUCCESS ((uint16_t)0)
#define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013)
typedef void (*hv_vmbus_channel_callback)(void *context);
@@ -471,10 +472,17 @@ typedef enum {
HV_CPU_ID_FUNCTION_MS_HV_VERSION = 0x40000002,
HV_CPU_ID_FUNCTION_MS_HV_FEATURES = 0x40000003,
HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION = 0x40000004,
- HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005
-
+ HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005,
+ HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE = 0x40000006
} hv_vmbus_cpuid_function;
+#define HV_FEATURE_MSR_TIME_REFCNT (1 << 1)
+#define HV_FEATURE_MSR_SYNCIC (1 << 2)
+#define HV_FEATURE_MSR_STIMER (1 << 3)
+#define HV_FEATURE_MSR_APIC (1 << 4)
+#define HV_FEATURE_MSR_HYPERCALL (1 << 5)
+#define HV_FEATURE_MSR_GUEST_IDLE (1 << 10)
+
/*
* Define the format of the SIMP register
*/
@@ -628,6 +636,9 @@ typedef enum {
extern hv_vmbus_context hv_vmbus_g_context;
extern hv_vmbus_connection hv_vmbus_g_connection;
+extern u_int hyperv_features;
+extern u_int hyperv_recommends;
+
typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg);
typedef struct hv_vmbus_channel_msg_table_entry {
diff --git a/usr.bin/bsdiff/bspatch/bspatch.c b/usr.bin/bsdiff/bspatch/bspatch.c
index d2af3ca..92bc75b 100644
--- a/usr.bin/bsdiff/bspatch/bspatch.c
+++ b/usr.bin/bsdiff/bspatch/bspatch.c
@@ -155,6 +155,10 @@ int main(int argc,char * argv[])
};
/* Sanity-check */
+ if ((ctrl[0] < 0) || (ctrl[1] < 0))
+ errx(1,"Corrupt patch\n");
+
+ /* Sanity-check */
if(newpos+ctrl[0]>newsize)
errx(1,"Corrupt patch\n");
diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh
index 9fcc012..cac7091 100644
--- a/usr.sbin/freebsd-update/freebsd-update.sh
+++ b/usr.sbin/freebsd-update/freebsd-update.sh
@@ -1250,7 +1250,7 @@ fetch_metadata_sanity () {
# Check that the first four fields make sense.
if gunzip -c < files/$1.gz |
- grep -qvE "^[a-z]+\|[0-9a-z]+\|${P}+\|[fdL-]\|"; then
+ grep -qvE "^[a-z]+\|[0-9a-z-]+\|${P}+\|[fdL-]\|"; then
fetch_metadata_bogus ""
return 1
fi
OpenPOWER on IntegriCloud