diff options
author | sephe <sephe@FreeBSD.org> | 2016-10-13 04:32:55 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-10-13 04:32:55 +0000 |
commit | ed1cb0e5f9d50e4b97491452fc67c969e27dde9e (patch) | |
tree | 18c6750a6c1f044be4539bdf31d54b63c367c2bd /sys/dev/hyperv/utilities/hv_util.c | |
parent | 95095a057fcd16004d957aa1b41423755d4308f3 (diff) | |
download | FreeBSD-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.c | 69 |
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); |