[libvirt] [PATCH] nwfilter: Don't crash when trying to add an nwfilter that's already being removed

Ján Tomko jtomko at redhat.com
Tue Mar 19 16:30:03 UTC 2019


On Tue, Mar 19, 2019 at 05:09:33PM +0100, Michal Privoznik wrote:
>On 3/19/19 4:53 PM, Ján Tomko wrote:
>> On Mon, Mar 18, 2019 at 05:27:39PM +0100, Michal Privoznik wrote:
>>> https://bugzilla.redhat.com/show_bug.cgi?id=1686927
>>>
>>> When trying to create a nwfilter binding via
>>> nwfilterBindingCreateXML() we may encounter a crash. The sequence
>>> of functions called is as follows:
>>>
>>> 1) nwfilterBindingCreateXML() parses the XML and calls
>>> virNWFilterBindingObjListAdd() which calls
>>> virNWFilterBindingObjListAddLocked()
>>>
>>> 2) Here, @binding is not found because binding->remove is set.
>>>
>>> 3) Therefore, controls continue with creating new @binding,
>>> setting its def to the one from 1) and adding it to the hash
>>> table.
>>>
>>> 4) This fails, because the binding is still in the hash table
>>> (duplicate key is detected).
>>>
>>> 5) The control jumps to 'error' label where
>>> virNWFilterBindingObjEndAPI() is called which frees the binding
>>> definition passed.
>>>
>>> 6) Error is propagated to the caller, which calls
>>> virNWFilterBindingDefFree() over the definition again.
>>>
>>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>>> ---
>>> src/conf/virnwfilterbindingobjlist.c | 11 ++++++-----
>>> src/conf/virnwfilterbindingobjlist.h |  2 +-
>>> src/nwfilter/nwfilter_driver.c       |  5 ++---
>>> 3 files changed, 9 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/src/conf/virnwfilterbindingobjlist.c
>>> b/src/conf/virnwfilterbindingobjlist.c
>>> index 06ccbf53af..87189da642 100644
>>> --- a/src/conf/virnwfilterbindingobjlist.c
>>> +++ b/src/conf/virnwfilterbindingobjlist.c
>>> @@ -164,23 +164,24 @@
>>> virNWFilterBindingObjListAddObjLocked(virNWFilterBindingObjListPtr
>>> bindings,
>>>  */
>>> static virNWFilterBindingObjPtr
>>> virNWFilterBindingObjListAddLocked(virNWFilterBindingObjListPtr bindings,
>>> -                                   virNWFilterBindingDefPtr def)
>>> +                                   virNWFilterBindingDefPtr *def)
>>
>> Rather than adding another return value to the whole chain,
>>
>>> {
>>>     virNWFilterBindingObjPtr binding;
>>>
>>>     /* See if a binding with matching portdev already exists */
>>>     if ((binding = virNWFilterBindingObjListFindByPortDevLocked(
>>> -             bindings, def->portdevname))) {
>>> +             bindings, (*def)->portdevname))) {
>>>         virReportError(VIR_ERR_OPERATION_FAILED,
>>>                        _("binding '%s' already exists"),
>>> -                       def->portdevname);
>>> +                       (*def)->portdevname);
>>>         goto error;
>>>     }
>>>
>>>     if (!(binding = virNWFilterBindingObjNew()))
>>>         goto error;
>>>
>>> -    virNWFilterBindingObjSetDef(binding, def);
>>> +    virNWFilterBindingObjSetDef(binding, *def);
>>> +    *def = NULL;
>>>
>>>     if (virNWFilterBindingObjListAddObjLocked(bindings, binding) < 0)
>>
>> I'd simply set
>>    binding->def = NULL;
>> here, to match what virDomainObjListAddLocked does.
>
>How can this work? binding's structure is internal so the only way to do

Hmm, not good.
My other suggestions would be:
* create an ugly virNWFilterBindingObjResetDef API
* make another copy of the definition and make virNWFilterBindingObjListAdd
  always consume it

>diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
>index fdfc6f48fa..8c2e987b5d 100644
>--- a/src/nwfilter/nwfilter_driver.c
>+++ b/src/nwfilter/nwfilter_driver.c
>@@ -759,7 +759,7 @@ nwfilterBindingCreateXML(virConnectPtr conn,
>         goto cleanup;
>
>     obj = virNWFilterBindingObjListAdd(driver->bindings,
>-                                       def);
>+                                       &def);
>     if (!obj)
>         goto cleanup;

As-is, def would be NULL even on success and dereferenced on the next
line.

Jano

>
>@@ -775,8 +775,7 @@ nwfilterBindingCreateXML(virConnectPtr conn,
>     virNWFilterBindingObjSave(obj, driver->bindingDir);
>
>  cleanup:
>-    if (!obj)
>-        virNWFilterBindingDefFree(def);
>+    virNWFilterBindingDefFree(def);
>     virNWFilterBindingObjEndAPI(&obj);
>
>     return ret;


>this would be by calling virNWFilterBindingObjSetDef(binding, NULL)
>which would free @def immediatelly and thus we wouldn't avoid double
>free. Can you shed more light what you have on mind please?
>
>Thanks,
>Michal
>
>--
>libvir-list mailing list
>libvir-list at redhat.com
>https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190319/5d00f48f/attachment-0001.sig>


More information about the libvir-list mailing list