]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
VMCI QPair ops must check for valid queues.
authorVMware, Inc <>
Tue, 19 Oct 2010 19:50:21 +0000 (12:50 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Tue, 19 Oct 2010 19:50:21 +0000 (12:50 -0700)
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 <mvanzin@vmware.com>
open-vm-tools/modules/linux/vmci/vmciQPair.c
open-vm-tools/modules/linux/vmci/vmci_version.h

index b977a987f816c3d734a2dfe04cdfed9852042563..bfa0fcd52c0e3a98b3cfd6382b4b840254ac7cb8 100644 (file)
@@ -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,
index 8350a34eb86ec11572ff21d0b13d086e67480dbd..fb46426ebb33dd3381f2ae940f3cdd2f8a133f20 100644 (file)
@@ -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_ */