[libvirt] [PATCH] macvtap: libvirtd forgot macvtap device name during a shutdown/restart cycle

Stefan Berger stefanb at linux.vnet.ibm.com
Wed Nov 3 13:03:46 UTC 2010


On 11/03/2010 07:21 AM, Daniel P. Berrange wrote:
> On Wed, Nov 03, 2010 at 07:16:53AM -0400, Stefan Berger wrote:
>> On 11/03/2010 06:43 AM, Daniel P. Berrange wrote:
>>> On Tue, Nov 02, 2010 at 07:04:01PM -0400, Stefan Berger wrote:
>>>> On 11/02/2010 11:47 AM, Daniel P. Berrange wrote:
>>>>> On Tue, Nov 02, 2010 at 11:35:44AM -0400, Stefan Berger wrote:
>>>>>> During a shutdown/restart cycle libvirtd forgot the macvtap device name
>>>>>> that it had created on behalf of a VM so that a stale macvtap device
>>>>>> remained on the host when the VM terminated. Libvirtd has to actively
>>>>>> tear down a macvtap device and it uses its name for identifying which
>>>>>> device to tear down.
>>>>>>
>>>>>> The solution is to not blank out the<target dev='...'/>    completely,
>>>>>> but
>>>>>> only blank it out on VMs that are not active. So, if a VM is active, the
>>>>>> device name makes it into the XML and is also being parsed. If a VM is
>>>>>> not active, the device name is discarded.
>>>>>>
>>>>>> Signed-off-by: Stefan Berger<stefanb at us.ibm.com>
>>>>>>
>>>>>> ---
>>>>>>   src/conf/domain_conf.c |    5 ++++-
>>>>>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> Index: libvirt-acl/src/conf/domain_conf.c
>>>>>> ===================================================================
>>>>>> --- libvirt-acl.orig/src/conf/domain_conf.c
>>>>>> +++ libvirt-acl/src/conf/domain_conf.c
>>>>>> @@ -2343,7 +2343,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
>>>>>>           def->data.direct.linkdev = dev;
>>>>>>           dev = NULL;
>>>>>>
>>>>>> -        VIR_FREE(ifname);
>>>>>> +        if ((flags&    VIR_DOMAIN_XML_INACTIVE))
>>>>>> +            VIR_FREE(ifname);
>>>>> The conditional isn't required here - it is already dealt
>>>>> with earlier on in the file. Just remove the VIR_FREE
>>>>> completely.
>>>>>
>>>> The conditional further above is this code fragment here:
>>>>
>>>>              } else if ((ifname == NULL)&&
>>>>                         xmlStrEqual(cur->name, BAD_CAST "target")) {
>>>>                  ifname = virXMLPropString(cur, "dev");
>>>>                  if ((ifname != NULL)&&
>>>>                      ((flags&   VIR_DOMAIN_XML_INACTIVE)&&
>>>>                        (STRPREFIX((const char*)ifname, "vnet")))) {
>>>>                      /* An auto-generated target name, blank it out */
>>>>                      VIR_FREE(ifname);
>>>>                  }
>>>>
>>>> Unfortunately it is also testing for the prefix 'vnet'.
>>>>
>>>> In case of a macvtap device I don't want to pick up the name of the
>>>> macvtap device from the XML unless it's attached to a running domain. So
>>>> that's why I remove it above.
>>>>
>>>> If the domain went down without libvirt 'seeing' it then we miessed out
>>>> on tearing it down and in that case there may be a stale device, but I
>>>> don't support this case. So I also want to have that cleared.
>>>>
>>>> Further, I also don't accept user-provided interface names for the
>>>> reason of tear-down in case of failures while trying to start a VM. In
>>>> the failure-case it is not clear anymore whether the name was
>>>> user-provided and was previously created and needs to be torn down or
>>>> simply is a user-provided name of an interface that wasn't created and
>>>> thus should not be torn down because it may actually be clashing with
>>>> the user-provided name of a running VM. I had that before and this ended
>>>> up running danger of tearing down interfaces of running VMs when a
>>>> failure-path was invoked.
>>> Hmm, I didn't notice that macvtap didn't allow user provided interface
>>> names. IMHO this is a bug, because many users like to have predetermined
>>> names for the devices to allow easy matching up to VMs.
>>>
>>> The problem scenario you describe here with teardown killing the
>>> interface of another running guests, only occurs if the admin has
>>> configured two guests with the same macvtap device name. This is
>>> user error. We're punishing everybody by disallowing user provided
>>> names, just in case a minority create a broken config :-(
>> I think in case of macvtap this would create more security holes than
>> provide a benefit. To be safe that the name of an interface is not
>> already used, we'd have to cross-check with all other domains'
>> interfaces, otherwise people will wonder what happened when a VM
>> couldn't start and now another VM doesn't have its interface anymore.
>> People do forget what names they provided to interfaces. Can multiple
>> users define domains on the same machine and create those clashes? If
>> there was an elegant solution, I'd like to support it, but for now
>> fixing the libvirtd's forgetfullness is more important.. also since it's
>> just a netto one-liner...
> I'm not debating that its possible to create problems in the way you
> describe, but AFAICT, this is no different to what can go wrong with
> normal TAP devices. IMHO the policy for this should be the same
> for macvtap and tap.
I believe a solution to support user-provide macvtap device names would 
be to:

- introduce a boolean in the direct device structure indicating whether 
the device was created, i.e., should be torn down in a failure path
- the function delMacvtapTap receives a boolean indicating whether it is 
invoked as part of a failure path;
     - if not a failure path, then the VM must have been started 
successfully and this is part of a detach or VM shutdown when we tear 
down the device blindly; this also covers the case when the boolean 
above was lost due to a libvirtd restart

     - if in a failure path, then the VM must have the boolean in the 
direct device structure set to be torn down; the failure path is invoked 
also as part of invoking qemudShutdownVMDaemon, but that function also 
seems to be invoked as part of proper cleanup -> now it would have to 
have a boolean indicating what the reason is for its invocation, i.e., 
get a 'true' at least when invoked in the cleanup path of 
qemudStartVMDaemon() to indicate the failure path.

How does this sound?

    Stefan
> Daniel




More information about the libvir-list mailing list