]> xenbits.xensource.com Git - libvirt.git/commitdiff
rpc: Don't rewrite msg->fds on every read dispatch
authorBen Gray <ben.r.gray@gmail.com>
Thu, 26 Nov 2015 16:10:40 +0000 (16:10 +0000)
committerMartin Kletzander <mkletzan@redhat.com>
Tue, 12 Jan 2016 07:56:50 +0000 (08:56 +0100)
When we are receiving data in smaller chunks it might happen that
virNetServerClientDispatchRead() will be called multiple times.  And as
that happens, if it is a message that also transfer headers, we decode
the number of them every single time and, unfortunately, also allocate
the memory for them.  That causes a leak, in the best scenario.

Best viewed with '-w'.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
src/rpc/virnetserverclient.c

index 0e3a71f9b2710e8e547a6050ad21c1601bccd0b8..64dab46314281a6b23940ca399e450d685cea11e 100644 (file)
@@ -1107,36 +1107,38 @@ static void virNetServerClientDispatchRead(virNetServerClientPtr client)
 
         /* Now figure out if we need to read more data to get some
          * file descriptors */
-        if (msg->header.type == VIR_NET_CALL_WITH_FDS &&
-            virNetMessageDecodeNumFDs(msg) < 0) {
-            virNetMessageQueueServe(&client->rx);
-            virNetMessageFree(msg);
-            client->wantClose = true;
-            return; /* Error */
-        }
-
-        /* Try getting the file descriptors (may fail if blocking) */
-        for (i = msg->donefds; i < msg->nfds; i++) {
-            int rv;
-            if ((rv = virNetSocketRecvFD(client->sock, &(msg->fds[i]))) < 0) {
+        if (msg->header.type == VIR_NET_CALL_WITH_FDS) {
+            if (msg->nfds == 0 &&
+                virNetMessageDecodeNumFDs(msg) < 0) {
                 virNetMessageQueueServe(&client->rx);
                 virNetMessageFree(msg);
                 client->wantClose = true;
-                return;
+                return; /* Error */
             }
-            if (rv == 0) /* Blocking */
-                break;
-            msg->donefds++;
-        }
 
-        /* Need to poll() until FDs arrive */
-        if (msg->donefds < msg->nfds) {
-            /* Because DecodeHeader/NumFDs reset bufferOffset, we
-             * put it back to what it was, so everything works
-             * again next time we run this method
-             */
-            client->rx->bufferOffset = client->rx->bufferLength;
-            return;
+            /* Try getting the file descriptors (may fail if blocking) */
+            for (i = msg->donefds; i < msg->nfds; i++) {
+                int rv;
+                if ((rv = virNetSocketRecvFD(client->sock, &(msg->fds[i]))) < 0) {
+                    virNetMessageQueueServe(&client->rx);
+                    virNetMessageFree(msg);
+                    client->wantClose = true;
+                    return;
+                }
+                if (rv == 0) /* Blocking */
+                    break;
+                msg->donefds++;
+            }
+
+            /* Need to poll() until FDs arrive */
+            if (msg->donefds < msg->nfds) {
+                /* Because DecodeHeader/NumFDs reset bufferOffset, we
+                 * put it back to what it was, so everything works
+                 * again next time we run this method
+                 */
+                client->rx->bufferOffset = client->rx->bufferLength;
+                return;
+            }
         }
 
         /* Definitely finished reading, so remove from queue */