[libvirt] [PATCH libvirt v2 4/9] remote: Use domainClientEventCallbacks for remoteReplayConnectionClosedEvent

John Ferlan jferlan at redhat.com
Fri Apr 27 00:19:35 UTC 2018



On 04/26/2018 12:27 PM, Marc Hartmayer wrote:
> On Thu, Apr 26, 2018 at 05:07 PM +0200, John Ferlan <jferlan at redhat.com> wrote:
>> On 04/12/2018 08:40 AM, Marc Hartmayer wrote:
>>> This allows us to get rid of another usage of the global variable
>>> remoteProgram.
>>>
>>> Signed-off-by: Marc Hartmayer <mhartmay at linux.vnet.ibm.com>
>>> Reviewed-by: Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
>>> ---
>>>  src/remote/remote_daemon_dispatch.c | 18 ++++++++++++++----
>>>  1 file changed, 14 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
>>> index b4c0e01b0832..cf2cd0add7d6 100644
>>> --- a/src/remote/remote_daemon_dispatch.c
>>> +++ b/src/remote/remote_daemon_dispatch.c
>>> @@ -1661,12 +1661,12 @@ remoteRelayDomainQemuMonitorEvent(virConnectPtr conn,
>>>  static
>>>  void remoteRelayConnectionClosedEvent(virConnectPtr conn ATTRIBUTE_UNUSED, int reason, void *opaque)
>>>  {
>>> -    virNetServerClientPtr client = opaque;
>>> +    daemonClientEventCallbackPtr callback = opaque;
>>>
>>>      VIR_DEBUG("Relaying connection closed event, reason %d", reason);
>>>
>>>      remote_connect_event_connection_closed_msg msg = { reason };
>>> -    remoteDispatchObjectEventSend(client, remoteProgram,
>>> +    remoteDispatchObjectEventSend(callback->client, callback->program,
>>>                                    REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED,
>>>                                    (xdrproc_t)xdr_remote_connect_event_connection_closed_msg,
>>>                                    &msg);
>>> @@ -3836,6 +3836,7 @@ remoteDispatchConnectRegisterCloseCallback(virNetServerPtr server ATTRIBUTE_UNUS
>>>                                             virNetMessageErrorPtr rerr)
>>>  {
>>>      int rv = -1;
>>> +    daemonClientEventCallbackPtr callback = NULL;
>>>      struct daemonClientPrivate *priv =
>>>          virNetServerClientGetPrivateData(client);
>>>
>>> @@ -3846,9 +3847,16 @@ remoteDispatchConnectRegisterCloseCallback(virNetServerPtr server ATTRIBUTE_UNUS
>>>          goto cleanup;
>>>      }
>>>
>>> +    if (VIR_ALLOC(callback) < 0)
>>> +        goto cleanup;
>>> +    callback->client = virObjectRef(client);
>>
>> Oh and this would seem to fix a problem with the callback possibly using
>> @client after it had been freed!
> 
> The problem is more of a theoretical nature as Nikolay had explained:
> 
> “Refcounting was here originally but then removed in [1] as it conflicts with
> virConnectRegisterCloseCallback returns 0 in case connectRegisterCloseCallback
> is not implemented. This is safe though (at least nobody touch this place :).
> 
> [1] ce35122cfe: "daemon: fixup refcounting in close callback handling"”
> 
>>
>>> +    callback->program = virObjectRef(remoteProgram);
>>> +    /* eventID, callbackID, and legacy are not used */
>>> +    callback->eventID = -1;
>>> +    callback->callbackID = -1;
>>>      if (virConnectRegisterCloseCallback(priv->conn,
>>>                                          remoteRelayConnectionClosedEvent,
>>> -                                        client, NULL) < 0)
>>> +                                        callback, remoteEventCallbackFree) < 0)
>>>          goto cleanup;
>>>
>>
>> @callback would be leaked in the normal path...
> 
> By normal path, you mean without the first patch?
> 

I was following how the other register functions proceeded and they
saved the callback in a list to be freed at unregister.  So if Register
succeeds, rv == 0 and the removeEventCallbackFree(callback) isn't called
and we leak callback.  At least that's how I read it

John

>> If you consider all the
>> other callbacks will load @callback onto some list that gets run during
>> remoteClientFreePrivateCallbacks via DEREG_CB, this code would need to
>> do something similar. Since there's only 1 it's perhaps easier at
>> least.
>>
>>>      priv->closeRegistered = true;
>>
>> Perhaps change closeRegistered from bool to daemonClientEventCallbackPtr
>> and handle it that way similar to how other callback processing is
>> handled.
> 
> This would be one way how to deal with it (even without the first
> patch). But a double free error must be prevented.
> 
>>
>> John
>>
>>> @@ -3856,8 +3864,10 @@ remoteDispatchConnectRegisterCloseCallback(virNetServerPtr server ATTRIBUTE_UNUS
>>>
>>>   cleanup:
>>>      virMutexUnlock(&priv->lock);
>>> -    if (rv < 0)
>>> +    if (rv < 0) {
>>> +        remoteEventCallbackFree(callback);
>>>          virNetMessageSaveError(rerr);
>>> +    }
>>>      return rv;
>>>  }
>>>
>>>
>>
> --
> Beste Grüße / Kind regards
>    Marc Hartmayer
> 
> IBM Deutschland Research & Development GmbH
> Vorsitzende des Aufsichtsrats: Martina Koederitz
> Geschäftsführung: Dirk Wittkopp
> Sitz der Gesellschaft: Böblingen
> Registergericht: Amtsgericht Stuttgart, HRB 243294
> 




More information about the libvir-list mailing list