Re: [PATCH 3/6] rpc: Plug memory leak on virNetClientSendInternal() error path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/01/2011 07:11 AM, Eric Blake wrote:
On 11/29/2011 11:40 PM, Alex Jia wrote:
On 11/30/2011 02:26 PM, Wen Congyang wrote:
At 11/30/2011 01:57 PM, ajia@xxxxxxxxxx Write:
From: Alex Jia<ajia@xxxxxxxxxx>

Detected by Coverity. Leak introduced in commit 673adba.

So I think we should not free call if it is still on the queue.
Yeah, it's a inappropriate place, in addition, in 'cleanup' label, if
ret !=1, also will free 'all', then 'unlock' label still do this, the
following should be a right place:

1708     if (!client->sock || client->wantClose) {
1709         virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
1710                     _("client socket is closed"));
*1711       VIR_FREE(call);*
1712         goto unlock;
1713     }
Closer, but still not quite right either.  You solved the failure if
!client->sock, but still left in the bug that a failed virCondInit did
goto cleanup, which then did a call to virCondDestroy on uninitialized
data, which is undefined by POSIX.

Rearranging some code and consolidating to one label will solve both
bugs (the leak if !client->sock, and the incorrect virCondDestroy call
on virCondInit failure), while still avoiding to free call on a partial
send.  Here's what I'm pushing under your name.
Yeah, I just saw codes again. Eric, thanks.
diff --git c/src/rpc/virnetclient.c w/src/rpc/virnetclient.c
index a738129..5165c8d 100644
--- c/src/rpc/virnetclient.c
+++ w/src/rpc/virnetclient.c
@@ -1705,13 +1705,13 @@ static int
virNetClientSendInternal(virNetClientPtr client,

      virNetClientLock(client);

      if (!client->sock || client->wantClose) {
          virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                      _("client socket is closed"));
-        goto unlock;
+        goto cleanup;
      }

      if (virCondInit(&call->cond)<  0) {
          virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                      _("cannot initialize condition variable"));
          goto cleanup;
@@ -1726,22 +1726,22 @@ static int
virNetClientSendInternal(virNetClientPtr client,
      call->expectReply = expectReply;
      call->nonBlock = nonBlock;
      call->haveThread = true;

      ret = virNetClientIO(client, call);

-cleanup:
      /* If partially sent, then the call is still on the dispatch queue */
      if (ret == 1) {
          call->haveThread = false;
      } else {
          ignore_value(virCondDestroy(&call->cond));
-        VIR_FREE(call);
      }

-unlock:
+cleanup:
+    if (ret != 1)
+        VIR_FREE(call);
      virNetClientUnlock(client);
      return ret;
  }


  /*


--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]