Hi Paul, Can you point out the particular code that fixed the access violation?
I looked at the code, and code such as the following is redundant: + // We need to ensure we have enough data to process + if (NlMsgSize(&ovsMsg->nlMsg) > ovsMsgLength) { + status = STATUS_INVALID_PARAMETER; + goto done; + } We already validate the minimum required length when we call into MapIrpOutputBuffer(). Also, it would be helpful for review if we limited each patch to address one problem. I see fixes in Flow.c and Datpath.c. Are they all related to the same problem you are trying to address? -- Nithin -----Original Message----- From: dev <dev-boun...@openvswitch.org> on behalf of Paul Boca <pb...@cloudbasesolutions.com> Date: Wednesday, April 27, 2016 at 1:05 AM To: "dev@openvswitch.org" <dev@openvswitch.org> Subject: [ovs-dev] [PATCH V2] datapath-windows: Validate netlink packets integrity >Solved access violation when trying to acces netling message - obtained >with forged IOCTLs > >Signed-off-by: Paul-Daniel Boca <pb...@cloudbasesolutions.com> >Acked-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com> >--- >V2: Fixed alignement problems >--- > datapath-windows/ovsext/Datapath.c | 45 ++++++++++++++++++--- > datapath-windows/ovsext/Flow.c | 42 +++++++++++--------- > datapath-windows/ovsext/Netlink/Netlink.c | 66 >++++++++++++++++++++++++++----- > datapath-windows/ovsext/Netlink/Netlink.h | 13 ++++-- > datapath-windows/ovsext/User.c | 5 ++- > datapath-windows/ovsext/Vport.c | 34 ++++++++-------- > lib/netlink-socket.c | 2 + > 7 files changed, 152 insertions(+), 55 deletions(-) > >diff --git a/datapath-windows/ovsext/Datapath.c >b/datapath-windows/ovsext/Datapath.c >index 06f99b3..1f89964 100644 >--- a/datapath-windows/ovsext/Datapath.c >+++ b/datapath-windows/ovsext/Datapath.c >@@ -307,6 +307,7 @@ static NTSTATUS MapIrpOutputBuffer(PIRP irp, > static NTSTATUS ValidateNetlinkCmd(UINT32 devOp, > POVS_OPEN_INSTANCE instance, > POVS_MESSAGE ovsMsg, >+ UINT32 ovsMgsLength, > NETLINK_FAMILY *nlFamilyOps); > static NTSTATUS InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT >usrParamsCtx, > NETLINK_FAMILY *nlFamilyOps, >@@ -694,6 +695,7 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject, > UINT32 devOp; > OVS_MESSAGE ovsMsgReadOp; > POVS_MESSAGE ovsMsg; >+ UINT32 ovsMsgLength = 0; > NETLINK_FAMILY *nlFamilyOps; > OVS_USER_PARAMS_CONTEXT usrParamsCtx; > >@@ -774,6 +776,7 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject, > } > > ovsMsg = inputBuffer; >+ ovsMsgLength = inputBufferLen; > devOp = OVS_TRANSACTION_DEV_OP; > break; > >@@ -808,6 +811,7 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject, > OVS_CTRL_CMD_EVENT_NOTIFY : > OVS_CTRL_CMD_READ_NOTIFY; > ovsMsg->genlMsg.version = nlControlFamilyOps.version; >+ ovsMsgLength = outputBufferLen; > > devOp = OVS_READ_DEV_OP; > break; >@@ -853,6 +857,7 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject, > > /* Create an NL message for consumption. */ > ovsMsg = &ovsMsgReadOp; >+ ovsMsgLength = sizeof (ovsMsgReadOp); > devOp = OVS_READ_DEV_OP; > > break; >@@ -864,7 +869,21 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject, > goto done; > } > >+ /* >+ * Output buffer not mandatory but map it in case we have >something >+ * to return to requester. >+ */ >+ if (outputBufferLen != 0) { >+ status = MapIrpOutputBuffer(irp, outputBufferLen, >+ sizeof *ovsMsg, &outputBuffer); >+ if (status != STATUS_SUCCESS) { >+ goto done; >+ } >+ ASSERT(outputBuffer); >+ } >+ > ovsMsg = inputBuffer; >+ ovsMsgLength = inputBufferLen; > devOp = OVS_WRITE_DEV_OP; > break; > >@@ -903,7 +922,8 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject, > * "artificial" or was copied from a previously validated 'ovsMsg'. > */ > if (devOp != OVS_READ_DEV_OP) { >- status = ValidateNetlinkCmd(devOp, instance, ovsMsg, >nlFamilyOps); >+ status = ValidateNetlinkCmd(devOp, instance, ovsMsg, >+ ovsMsgLength, nlFamilyOps); > if (status != STATUS_SUCCESS) { > goto done; > } >@@ -938,11 +958,18 @@ static NTSTATUS > ValidateNetlinkCmd(UINT32 devOp, > POVS_OPEN_INSTANCE instance, > POVS_MESSAGE ovsMsg, >+ UINT32 ovsMsgLength, > NETLINK_FAMILY *nlFamilyOps) > { > NTSTATUS status = STATUS_INVALID_PARAMETER; > UINT16 i; > >+ // We need to ensure we have enough data to process >+ if (NlMsgSize(&ovsMsg->nlMsg) > ovsMsgLength) { >+ status = STATUS_INVALID_PARAMETER; >+ goto done; >+ } >+ > for (i = 0; i < nlFamilyOps->opsCount; i++) { > if (nlFamilyOps->cmds[i].cmd == ovsMsg->genlMsg.cmd) { > /* Validate if the command is valid for the device >operation. */ >@@ -977,6 +1004,14 @@ ValidateNetlinkCmd(UINT32 devOp, > } > } > >+ // validate all NlAttrs >+ if (!NlValidateAllAttrs(&ovsMsg->nlMsg, sizeof(*ovsMsg), >+ NlMsgAttrsLen((PNL_MSG_HDR)ovsMsg), >+ NULL, 0)) { >+ status = STATUS_INVALID_PARAMETER; >+ goto done; >+ } >+ > done: > return status; > } >@@ -1028,6 +1063,7 @@ InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT >usrParamsCtx, > POVS_MESSAGE msgIn = NULL; > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > > if (usrParamsCtx->ovsMsg->genlMsg.cmd == >OVS_CTRL_CMD_EVENT_NOTIFY || > usrParamsCtx->ovsMsg->genlMsg.cmd == >OVS_CTRL_CMD_READ_NOTIFY) { >@@ -1043,8 +1079,7 @@ InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT >usrParamsCtx, > > ASSERT(msgIn); > ASSERT(msgError); >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, >replyLen); > } > > if (*replyLen != 0) { >@@ -1416,9 +1451,9 @@ cleanup: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > > return STATUS_SUCCESS; >diff --git a/datapath-windows/ovsext/Flow.c >b/datapath-windows/ovsext/Flow.c >index a49a60c..792b614 100644 >--- a/datapath-windows/ovsext/Flow.c >+++ b/datapath-windows/ovsext/Flow.c >@@ -285,20 +285,10 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT >usrParamsCtx, > goto done; > } > >- /* Get all the top level Flow attributes */ >- if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr), >- nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy), >- flowAttrs, ARRAY_SIZE(flowAttrs))) >- != TRUE) { >- OVS_LOG_ERROR("Attr Parsing failed for msg: %p", >- nlMsgHdr); >- rc = STATUS_INVALID_PARAMETER; >- goto done; >- } >- >- /* FLOW_DEL command w/o any key input is a flush case. */ >+ /* FLOW_DEL command w/o any key input is a flush case. >+ If we don't have any attr, we treat this as a flush command*/ > if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) && >- (!(flowAttrs[OVS_FLOW_ATTR_KEY]))) { >+ (!NlMsgAttrsLen(nlMsgHdr))) { > > rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex); > >@@ -323,6 +313,17 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT >usrParamsCtx, > goto done; > } > >+ /* Get all the top level Flow attributes */ >+ if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr), >+ nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy), >+ flowAttrs, ARRAY_SIZE(flowAttrs))) >+ != TRUE) { >+ OVS_LOG_ERROR("Attr Parsing failed for msg: %p", >+ nlMsgHdr); >+ rc = STATUS_INVALID_PARAMETER; >+ goto done; >+ } >+ > if (flowAttrs[OVS_FLOW_ATTR_PROBE]) { > rc = OvsProbeSupportedFeature(msgIn, >flowAttrs[OVS_FLOW_ATTR_KEY]); > if (rc != STATUS_SUCCESS) { >@@ -399,8 +400,9 @@ done: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; >+ >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > rc = STATUS_SUCCESS; > } > >@@ -568,8 +570,9 @@ done: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; >+ >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > rc = STATUS_SUCCESS; > } > >@@ -706,8 +709,9 @@ done: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; >+ >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > rc = STATUS_SUCCESS; > } > >diff --git a/datapath-windows/ovsext/Netlink/Netlink.c >b/datapath-windows/ovsext/Netlink/Netlink.c >index 27dcd4f..dc1e78c 100644 >--- a/datapath-windows/ovsext/Netlink/Netlink.c >+++ b/datapath-windows/ovsext/Netlink/Netlink.c >@@ -108,12 +108,18 @@ NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType, > * >-------------------------------------------------------------------------- >- > */ > VOID >-NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, UINT >errorCode) >+NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, >+ UINT32 msgErrorLen, >+ UINT errorCode, UINT32 *msgLen) > { > NL_BUFFER nlBuffer; > > ASSERT(errorCode != NL_ERROR_PENDING); > >+ if ((msgError == NULL) || (msgErrorLen < sizeof *msgError)) { >+ return; >+ } >+ > NlBufInit(&nlBuffer, (PCHAR)msgError, sizeof *msgError); > NlFillNlHdr(&nlBuffer, NLMSG_ERROR, 0, > msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid); >@@ -121,6 +127,10 @@ NlBuildErrorMsg(POVS_MESSAGE msgIn, >POVS_MESSAGE_ERROR msgError, UINT errorCode) > msgError->errorMsg.error = errorCode; > msgError->errorMsg.nlMsg = msgIn->nlMsg; > msgError->nlMsg.nlmsgLen = sizeof(OVS_MESSAGE_ERROR); >+ >+ if (NULL != msgLen) { >+ *msgLen = msgError->nlMsg.nlmsgLen; >+ } > } > > /* >@@ -1006,7 +1016,7 @@ NlAttrFind__(const PNL_ATTR attrs, UINT32 size, >UINT16 type) > { > PNL_ATTR iter = NULL; > PNL_ATTR ret = NULL; >- UINT32 left; >+ INT left; > > NL_ATTR_FOR_EACH (iter, left, attrs, size) { > if (NlAttrType(iter) == type) { >@@ -1036,6 +1046,49 @@ NlAttrFindNested(const PNL_ATTR nla, UINT16 type) > > /* > >*------------------------------------------------------------------------- >--- >+ * Traverses all attributes in received buffer in order to insure all >are valid >+ >*------------------------------------------------------------------------- >--- >+ */ >+BOOLEAN NlValidateAllAttrs(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, >+ UINT32 totalAttrLen, >+ const NL_POLICY policy[], const UINT32 >numPolicy) >+{ >+ PNL_ATTR nla; >+ INT left; >+ BOOLEAN ret = TRUE; >+ >+ if ((NlMsgSize(nlMsg) < attrOffset)) { >+ OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d", >+ nlMsg, attrOffset); >+ ret = FALSE; >+ goto done; >+ } >+ >+ NL_ATTR_FOR_EACH_UNSAFE(nla, left, NlMsgAt(nlMsg, attrOffset), >+ totalAttrLen) >+ { >+ if (!NlAttrIsValid(nla, left)) { >+ ret = FALSE; >+ goto done; >+ } >+ >+ UINT16 type = NlAttrType(nla); >+ if (type < numPolicy && policy[type].type != NL_A_NO_ATTR) { >+ /* Typecasting to keep the compiler happy */ >+ const PNL_POLICY e = (const PNL_POLICY)(&policy[type]); >+ if (!NlAttrValidate(nla, e)) { >+ ret = FALSE; >+ goto done; >+ } >+ } >+ } >+ >+done: >+ return ret; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- > * Parses the netlink message at a given offset (attrOffset) > * as a series of attributes. A pointer to the attribute with type > * 'type' is stored in attrs at index 'type'. policy is used to define >the >@@ -1052,20 +1105,13 @@ NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 >attrOffset, > PNL_ATTR attrs[], UINT32 numAttrs) > { > PNL_ATTR nla; >- UINT32 left; >+ INT left; > UINT32 iter; > BOOLEAN ret = FALSE; > UINT32 numPolicyAttr = MIN(numPolicy, numAttrs); > > RtlZeroMemory(attrs, numAttrs * sizeof *attrs); > >- >- /* There is nothing to parse */ >- if (!(NlMsgAttrsLen(nlMsg))) { >- ret = TRUE; >- goto done; >- } >- > if ((NlMsgSize(nlMsg) < attrOffset)) { > OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d", > nlMsg, attrOffset); >diff --git a/datapath-windows/ovsext/Netlink/Netlink.h >b/datapath-windows/ovsext/Netlink/Netlink.h >index 8f6a5be..63164c7 100644 >--- a/datapath-windows/ovsext/Netlink/Netlink.h >+++ b/datapath-windows/ovsext/Netlink/Netlink.h >@@ -72,6 +72,7 @@ typedef struct _NL_POLICY > /* This macro is careful to check for attributes with bad lengths. */ > #define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \ > for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ >+ ((INT)LEFT) >= (INT)NLA_ALIGN(sizeof(NL_ATTR)) && \ > NlAttrIsValid(ITER, LEFT); \ > (LEFT) -= NlAttrLenPad(ITER, LEFT), (ITER) = NlAttrNext(ITER)) > >@@ -80,7 +81,7 @@ typedef struct _NL_POLICY > * already been validated (e.g. with NL_ATTR_FOR_EACH). */ > #define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \ > for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ >- (LEFT) > 0; \ >+ ((INT)LEFT) >= (INT)NLA_ALIGN(sizeof(NL_ATTR)); \ > (LEFT) -= NLA_ALIGN((ITER)->nlaLen), (ITER) = NlAttrNext(ITER)) > > #define NL_ATTR_GET_AS(NLA, TYPE) \ >@@ -94,8 +95,9 @@ BOOLEAN NlFillNlHdr(PNL_BUFFER nlBuf, > UINT16 nlmsgType, UINT16 nlmsgFlags, > UINT32 nlmsgSeq, UINT32 nlmsgPid); > >-VOID NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgOut, >- UINT errorCode); >+VOID NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, >+ UINT32 msgErrorLen, >+ UINT errorCode, UINT32 *msgLen); > > /* Netlink message accessing the payload */ > PVOID NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset); >@@ -187,6 +189,11 @@ static __inline NlAttrIsLast(const PNL_ATTR nla, int >rem) > /* Netlink attribute validation */ > BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY); > >+/* Netlink attribute stream validation */ >+BOOLEAN NlValidateAllAttrs(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, >+ UINT32 totalAttrLen, >+ const NL_POLICY policy[], const UINT32 numPolicy); >+ > /* Put APis */ > BOOLEAN NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg); > BOOLEAN NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg); >diff --git a/datapath-windows/ovsext/User.c >b/datapath-windows/ovsext/User.c >index 33cbd89..bc010c7 100644 >--- a/datapath-windows/ovsext/User.c >+++ b/datapath-windows/ovsext/User.c >@@ -345,8 +345,9 @@ OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT >usrParamsCtx, > > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; >+ >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, >replyLen); > status = STATUS_SUCCESS; > goto done; > } >diff --git a/datapath-windows/ovsext/Vport.c >b/datapath-windows/ovsext/Vport.c >index d04b12b..4299169 100644 >--- a/datapath-windows/ovsext/Vport.c >+++ b/datapath-windows/ovsext/Vport.c >@@ -1729,9 +1729,9 @@ cleanup: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > > return STATUS_SUCCESS; >@@ -2088,9 +2088,9 @@ Cleanup: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > > return STATUS_SUCCESS; >@@ -2324,6 +2324,7 @@ Cleanup: > if ((nlError != NL_ERROR_SUCCESS) && (nlError != NL_ERROR_PENDING)) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > > if (vport && vportAllocated == TRUE) { > if (vportInitialized == TRUE) { >@@ -2343,8 +2344,7 @@ Cleanup: > OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG); > } > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > > return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS; >@@ -2452,9 +2452,9 @@ Cleanup: > if (nlError != NL_ERROR_SUCCESS) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > > return STATUS_SUCCESS; >@@ -2544,9 +2544,9 @@ Cleanup: > if ((nlError != NL_ERROR_SUCCESS) && (nlError != NL_ERROR_PENDING)) { > POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) > usrParamsCtx->outputBuffer; >+ UINT32 msgErrorLen = usrParamsCtx->outputLength; > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > > return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS; >@@ -2579,10 +2579,11 @@ OvsTunnelVportPendingRemove(PVOID context, > > *replyLen = msgOut->nlMsg.nlmsgLen; > } else { >- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut; >+ POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) >+ tunnelContext->outputBuffer; >+ UINT32 msgErrorLen = tunnelContext->outputLength; > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, >replyLen); > } > } > >@@ -2721,12 +2722,13 @@ OvsTunnelVportPendingInit(PVOID context, > } while (error); > > if (error) { >- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) msgOut; >+ POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) >+ tunnelContext->outputBuffer; >+ UINT32 msgErrorLen = tunnelContext->outputLength; > > OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL); > OvsFreeMemory(vport); > >- NlBuildErrorMsg(msgIn, msgError, nlError); >- *replyLen = msgError->nlMsg.nlmsgLen; >+ NlBuildErrorMsg(msgIn, msgError, msgErrorLen, nlError, replyLen); > } > } >diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c >index cad9490..32b0cc3 100644 >--- a/lib/netlink-socket.c >+++ b/lib/netlink-socket.c >@@ -127,6 +127,7 @@ nl_sock_create(int protocol, struct nl_sock **sockp) > sock = xmalloc(sizeof *sock); > > #ifdef _WIN32 >+ sock->overlapped.hEvent = NULL; > sock->handle = CreateFile(OVS_DEVICE_NAME_USER, > GENERIC_READ | GENERIC_WRITE, > FILE_SHARE_READ | FILE_SHARE_WRITE, >@@ -1191,6 +1192,7 @@ pend_io_request(struct nl_sock *sock) > > ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header); > ovs_header->dp_ifindex = 0; >+ nlmsg->nlmsg_len = request.size; > > if (!DeviceIoControl(sock->handle, OVS_IOCTL_WRITE, > request.data, request.size, >-- >2.7.2.windows.1 >_______________________________________________ >dev mailing list >dev@openvswitch.org >https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma >n_listinfo_dev&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pN >HQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=GabGAlmcY24uVSoAQCaiRYFIYSfiDS >JZomM6llWwZmA&s=N-QN8hqnSsvjfhoygdktRzwFa6jdc2QCMZelWxlsT3g&e= _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev