summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/utilities/hv_util.c
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-10-13 04:32:55 +0000
committersephe <sephe@FreeBSD.org>2016-10-13 04:32:55 +0000
commited1cb0e5f9d50e4b97491452fc67c969e27dde9e (patch)
tree18c6750a6c1f044be4539bdf31d54b63c367c2bd /sys/dev/hyperv/utilities/hv_util.c
parent95095a057fcd16004d957aa1b41423755d4308f3 (diff)
downloadFreeBSD-src-ed1cb0e5f9d50e4b97491452fc67c969e27dde9e.zip
FreeBSD-src-ed1cb0e5f9d50e4b97491452fc67c969e27dde9e.tar.gz
MFC 304730
hyperv/ic: Redefine IC version negotiate message. And stringent input IC version negotiate message checks. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7614
Diffstat (limited to 'sys/dev/hyperv/utilities/hv_util.c')
-rw-r--r--sys/dev/hyperv/utilities/hv_util.c69
1 files changed, 44 insertions, 25 deletions
diff --git a/sys/dev/hyperv/utilities/hv_util.c b/sys/dev/hyperv/utilities/hv_util.c
index e60a654..bb5b110 100644
--- a/sys/dev/hyperv/utilities/hv_util.c
+++ b/sys/dev/hyperv/utilities/hv_util.c
@@ -36,44 +36,62 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/reboot.h>
+#include <sys/systm.h>
#include <sys/timetc.h>
-#include <sys/syscallsubr.h>
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus.h>
-#include <dev/hyperv/utilities/hv_utilreg.h>
#include <dev/hyperv/utilities/hv_util.h>
+#include <dev/hyperv/utilities/vmbus_icreg.h>
#include "vmbus_if.h"
#define VMBUS_IC_BRSIZE (4 * PAGE_SIZE)
-void
-hv_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, uint8_t *buf)
+CTASSERT(sizeof(struct vmbus_icmsg_negotiate) < VMBUS_IC_BRSIZE);
+
+int
+vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int dlen)
{
- struct hv_vmbus_icmsg_negotiate *negop;
-
- icmsghdrp->icmsgsize = 0x10;
-
- negop = (struct hv_vmbus_icmsg_negotiate *)&buf[
- sizeof(struct hv_vmbus_pipe_hdr) +
- sizeof(struct hv_vmbus_icmsg_hdr)];
-
- if (negop->icframe_vercnt >= 2 &&
- negop->icversion_data[1].major == 3) {
- negop->icversion_data[0].major = 3;
- negop->icversion_data[0].minor = 0;
- negop->icversion_data[1].major = 3;
- negop->icversion_data[1].minor = 0;
- } else {
- negop->icversion_data[0].major = 1;
- negop->icversion_data[0].minor = 0;
- negop->icversion_data[1].major = 1;
- negop->icversion_data[1].minor = 0;
+ struct vmbus_icmsg_negotiate *nego;
+ int cnt, major;
+
+ /*
+ * Preliminary message size verification
+ */
+ if (dlen < sizeof(*nego)) {
+ device_printf(sc->ic_dev, "truncated ic negotiate, len %d\n",
+ dlen);
+ return EINVAL;
}
+ nego = data;
+
+ cnt = nego->ic_fwver_cnt + nego->ic_msgver_cnt;
+ if (dlen < __offsetof(struct vmbus_icmsg_negotiate, ic_ver[cnt])) {
+ device_printf(sc->ic_dev, "ic negotiate does not contain "
+ "versions %d\n", dlen);
+ return EINVAL;
+ }
+
+ /* Select major version; XXX looks wrong. */
+ if (nego->ic_fwver_cnt >= 2 && VMBUS_ICVER_MAJOR(nego->ic_ver[1]) == 3)
+ major = 3;
+ else
+ major = 1;
+
+ /* One framework version */
+ nego->ic_fwver_cnt = 1;
+ nego->ic_ver[0] = VMBUS_IC_VERSION(major, 0);
+
+ /* One message version */
+ nego->ic_msgver_cnt = 1;
+ nego->ic_ver[1] = VMBUS_IC_VERSION(major, 0);
+
+ /* Data contains two versions */
+ nego->ic_hdr.ic_dsize = __offsetof(struct vmbus_icmsg_negotiate,
+ ic_ver[2]) - sizeof(struct vmbus_icmsg_hdr);
- negop->icframe_vercnt = 1;
- negop->icmsg_vercnt = 1;
+ return 0;
}
int
@@ -101,6 +119,7 @@ hv_util_attach(device_t dev, vmbus_chan_callback_t cb)
struct vmbus_channel *chan = vmbus_get_channel(dev);
int error;
+ sc->ic_dev = dev;
sc->ic_buflen = VMBUS_IC_BRSIZE;
sc->receive_buffer = malloc(VMBUS_IC_BRSIZE, M_DEVBUF,
M_WAITOK | M_ZERO);
OpenPOWER on IntegriCloud