From: VMware, Inc <> Date: Tue, 19 Oct 2010 19:50:21 +0000 (-0700) Subject: VMCI QPair ops must check for valid queues. X-Git-Tag: 2010.10.18-313025~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=77a814cc6adcf71c16b3ce0066de9fabd0cb67f9;p=thirdparty%2Fopen-vm-tools.git VMCI QPair ops must check for valid queues. When a host (on hosted platforms) creates a VMCI queue pair, the actual queue content isn't available until a guest attaches, since the guest is responsible for creating the queue pair page files and handing them down to the host. Only at that point will pointers to queue data and queue header be valid. This works fine with VMCI Sockets in blocking mode, since connecting a stream socket only returns when both sides are attached to the queue pair. However, for non-blocking sockets, we will return earlier - while the stream socket is still in the connecting state. A subsequent poll to determine the state of the connecting stream socket may then attempt to access the queue header to figure out whether the socket has available data or free space. If the queue header is invalid, bad things happen. This change adds checks to the VMCIQPair API implementation, that detects queues with no data, and in that case reports the queues as having no available data or no free space, which is essentially true. For the operations that retrieves pointers, VMCI_ERROR_QUEUEPAIR_NOTATTACHED is now returned, since we don't want to depict a state that isn't correct. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/modules/linux/vmci/vmciQPair.c b/open-vm-tools/modules/linux/vmci/vmciQPair.c index b977a987f..bfa0fcd52 100644 --- a/open-vm-tools/modules/linux/vmci/vmciQPair.c +++ b/open-vm-tools/modules/linux/vmci/vmciQPair.c @@ -100,6 +100,9 @@ struct VMCIQPair { VMCIPrivilegeFlags privFlags; }; +#define VMCI_QPAIR_NO_QUEUE(_qp) (!(_qp)->produceQ->qHeader || \ + !(_qp)->consumeQ->qHeader) + /* *----------------------------------------------------------------------------- @@ -307,25 +310,33 @@ VMCIQPair_GetProduceIndexes(const VMCIQPair *qpair, // IN uint64 *producerTail, // OUT uint64 *consumerHead) // OUT { + int result; + if (!qpair) { return VMCI_ERROR_INVALID_ARGS; } VMCIQPairLock(qpair); - VMCIQueueHeader_GetPointers(qpair->produceQ->qHeader, - qpair->consumeQ->qHeader, - producerTail, - consumerHead); + if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) { + result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED; + } else { + VMCIQueueHeader_GetPointers(qpair->produceQ->qHeader, + qpair->consumeQ->qHeader, + producerTail, + consumerHead); + result = VMCI_SUCCESS; + } VMCIQPairUnlock(qpair); - if ((producerTail && *producerTail >= qpair->produceQSize) || - (consumerHead && *consumerHead >= qpair->produceQSize)) { + if (result == VMCI_SUCCESS && + ((producerTail && *producerTail >= qpair->produceQSize) || + (consumerHead && *consumerHead >= qpair->produceQSize))) { return VMCI_ERROR_INVALID_SIZE; } - return VMCI_SUCCESS; + return result; } @@ -353,25 +364,33 @@ VMCIQPair_GetConsumeIndexes(const VMCIQPair *qpair, // IN uint64 *consumerTail, // OUT uint64 *producerHead) // OUT { + int result; + if (!qpair) { return VMCI_ERROR_INVALID_ARGS; } VMCIQPairLock(qpair); - VMCIQueueHeader_GetPointers(qpair->consumeQ->qHeader, - qpair->produceQ->qHeader, - consumerTail, - producerHead); + if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) { + result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED; + } else { + VMCIQueueHeader_GetPointers(qpair->consumeQ->qHeader, + qpair->produceQ->qHeader, + consumerTail, + producerHead); + result = VMCI_SUCCESS; + } VMCIQPairUnlock(qpair); - if ((consumerTail && *consumerTail >= qpair->consumeQSize) || - (producerHead && *producerHead >= qpair->consumeQSize)) { + if (result == VMCI_SUCCESS && + ((consumerTail && *consumerTail >= qpair->consumeQSize) || + (producerHead && *producerHead >= qpair->consumeQSize))) { return VMCI_ERROR_INVALID_SIZE; } - return VMCI_SUCCESS; + return result; } @@ -407,9 +426,13 @@ VMCIQPair_ProduceFreeSpace(const VMCIQPair *qpair) // IN VMCIQPairLock(qpair); - result = VMCIQueueHeader_FreeSpace(qpair->produceQ->qHeader, - qpair->consumeQ->qHeader, - qpair->produceQSize); + if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) { + result = 0; + } else { + result = VMCIQueueHeader_FreeSpace(qpair->produceQ->qHeader, + qpair->consumeQ->qHeader, + qpair->produceQSize); + } VMCIQPairUnlock(qpair); @@ -450,9 +473,13 @@ VMCIQPair_ConsumeFreeSpace(const VMCIQPair *qpair) // IN VMCIQPairLock(qpair); - result = VMCIQueueHeader_FreeSpace(qpair->consumeQ->qHeader, - qpair->produceQ->qHeader, - qpair->consumeQSize); + if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) { + result = 0; + } else { + result = VMCIQueueHeader_FreeSpace(qpair->consumeQ->qHeader, + qpair->produceQ->qHeader, + qpair->consumeQSize); + } VMCIQPairUnlock(qpair); @@ -493,9 +520,13 @@ VMCIQPair_ProduceBufReady(const VMCIQPair *qpair) // IN VMCIQPairLock(qpair); - result = VMCIQueueHeader_BufReady(qpair->produceQ->qHeader, - qpair->consumeQ->qHeader, - qpair->produceQSize); + if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) { + result = 0; + } else { + result = VMCIQueueHeader_BufReady(qpair->produceQ->qHeader, + qpair->consumeQ->qHeader, + qpair->produceQSize); + } VMCIQPairUnlock(qpair); @@ -535,9 +566,13 @@ VMCIQPair_ConsumeBufReady(const VMCIQPair *qpair) // IN VMCIQPairLock(qpair); - result = VMCIQueueHeader_BufReady(qpair->consumeQ->qHeader, - qpair->produceQ->qHeader, - qpair->consumeQSize); + if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) { + result = 0; + } else { + result = VMCIQueueHeader_BufReady(qpair->consumeQ->qHeader, + qpair->produceQ->qHeader, + qpair->consumeQSize); + } VMCIQPairUnlock(qpair); @@ -561,6 +596,8 @@ VMCIQPair_ConsumeBufReady(const VMCIQPair *qpair) // IN * VMCI_ERROR_INVALID_SIZE, if any queue pointer is outside the queue * (as defined by the queue size). * VMCI_ERROR_INVALID_ARGS, if an error occured when accessing the buffer. + * VMCI_ERROR_QUEUEPAIR_NOTATTACHED, if the queue pair pages aren't + * available. * Otherwise, the number of bytes written to the queue is returned. * * Side effects: @@ -666,12 +703,12 @@ DequeueLocked(VMCIQueue *produceQ, // IN size_t read; ssize_t result; -#if defined _WIN32 && !defined VMX86_TOOLS && !defined VMX86_VMX +#if !defined VMX86_TOOLS && !defined VMX86_VMX if (UNLIKELY(!produceQ->qHeader || !consumeQ->qHeader)) { return VMCI_ERROR_QUEUEPAIR_NODATA; } -#endif /* Windows Host only support */ +#endif bufReady = VMCIQueueHeader_BufReady(consumeQ->qHeader, produceQ->qHeader, diff --git a/open-vm-tools/modules/linux/vmci/vmci_version.h b/open-vm-tools/modules/linux/vmci/vmci_version.h index 8350a34eb..fb46426eb 100644 --- a/open-vm-tools/modules/linux/vmci/vmci_version.h +++ b/open-vm-tools/modules/linux/vmci/vmci_version.h @@ -25,8 +25,8 @@ #ifndef _VMCI_VERSION_H_ #define _VMCI_VERSION_H_ -#define VMCI_DRIVER_VERSION 1.0.22.0 -#define VMCI_DRIVER_VERSION_COMMAS 1,0,22,0 -#define VMCI_DRIVER_VERSION_STRING "1.0.22.0" +#define VMCI_DRIVER_VERSION 1.0.23.0 +#define VMCI_DRIVER_VERSION_COMMAS 1,0,23,0 +#define VMCI_DRIVER_VERSION_STRING "1.0.23.0" #endif /* _VMCI_VERSION_H_ */