[libvirt PATCH 2/2] conf: log error on attempts to modify ACPI index of active device

Laine Stump laine at redhat.com
Fri Sep 10 15:18:20 UTC 2021


On 9/10/21 3:30 AM, Peter Krempa wrote:
> On Thu, Sep 09, 2021 at 13:46:41 -0400, Laine Stump wrote:
>> The ACPI index of a device in a running guest can't be modified, and
>> libvirt doesn't actually attempt to modify it, but it was possible for
>> a user to request such a modification, and libvirt wouldn't complain,
>> thus misleading the user into thinking that it had actually been changed.
>>
>> Resolves: https://bugzilla.redhat.com/1998920
>>
>> Signed-off-by: Laine Stump <laine at redhat.com>
>> ---
>>   src/conf/domain_conf.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>> index fefc527901..7ff890d8b7 100644
>> --- a/src/conf/domain_conf.c
>> +++ b/src/conf/domain_conf.c
>> @@ -28485,6 +28485,12 @@ virDomainDefCompatibleDevice(virDomainDef *def,
>>                              _("changing device alias is not allowed"));
>>               return -1;
>>           }
>> +
>> +        if (data.newInfo->acpiIndex != data.oldInfo->acpiIndex) {
>> +            virReportError(VIR_ERR_OPERATION_DENIED, "%s",
>> +                           _("changing device 'acpi index' is not allowed"));
>> +            return -1;
>> +        }
> 
> I don't remember any more what the intended semantics of the 'update'
> API are in regards to asking the user to provide a complete definition
> of the device, but according to the 'alias' check above we seem to be
> specifically ignoring the situation when the new definition didn't
> provide an alias. This seems to be hinting that we ignore stuff that the
> used didn't provide.
> 
> If that's the case you'll need to specifically exclude index '0' from
> the above check.

The difference here is that alias is something that normally is not set 
by the user, but is instead auto-generated by libvirt when the guest 
starts and not stored/reported in the persistent config. So in the 
common case of "grab config XML, extract device element, modify it, send 
it to update-device" the alias wouldn't be in the XML, but if the user 
instead grabs the *status* XML then the alias *would* be there. 
(However, if the alias had been set by the user (with the prefix "ua-"), 
the alias would be present in the config XML.) So we allow for either 
blank (in the case that config XML was used) or no-change (in case alias 
was user-set and/or the status XML is used).

The acpi index, on the other hand, is always unset unless the user 
specifies it, and so is never auto-generated and always matches in both 
the config and status XMLs. So whichever way the user gets the original 
XML (status or config) they are always going to have the actual setting.

There are many other attributes that are checked to assure they match in 
(e.g.) qemuDomainChangeNet() (for example, network device model name, 
virtio options, upscript name,...) and (with one exception) none of 
those check for "not specified or not changed" - they all just check for 
"not changed". The one exception is ifname, which is another attribute 
that (like alias) is autogenerated every time the guest starts, and is 
never output in config XML (unless it was user-specified); for ifname if 
it's been left unspecified in the update XML, then the value from the 
status is copied over, making it also effectively ("unspecified or 
unchanged"). But again, this special handling isn't done for any 
attribute that isn't both auto-generated and ephemeral (as alias and 
ifname are).

So in the end, I think it's correct that validation of acpi index 
*shouldn't* ignore an "apparently missing" value in the update.

======

BTW, something forgot to mention in the commit log - in the case of, 
e.g., network interfaces which is the only type of device where an alias 
is useful, most of the checks are in qemuDomainChangeNet() rather than 
in this virDomainDefCompatibleDevice() function. I was originally going 
to add this check into qemuDomainChangeNet() as well, but it is an 
attribute that's technically valid for any PCI device, not just 
interfaces; searching around, I found that 
virDomainDefCompatibleDevice() is called on update for all devices, and 
is already used to pretect against alias change (another attribute 
that's valid for all devices), so in the interest of consistency I put 
the check there.

That said, although I used it based on precendent, I can't say that I 
really like virDomainDefCompatibleDevice(). It is used for multiple 
unrelated things - the bit at the beginning of the function is only 
executed if action is UPDATE and live is true, and all the rest of the 
function is only useful if action is ATTACH - it's checking things that 
could verifiably never happen during a live device update (e.g. checking 
if the device is USB but the domain doesn't support USB devices, or 
checking attributes for a device type that isn't allowed to be updated 
at all.). So it's really 2 completely independent functions in one, 
where the final two args act as an extension to the function name.

I notice its action and live args previously weren't there - I did the 
spelunking into git history to find when/how; essentially there was at 
one time an unused action arg which was removed, but then re-added in 
order to add the check for alias). I didn't dig much deeper, but it 
seems like this might be an unnecessary tangle that should be split up 
into multiple functions. I didn't want to mess with that for a simple 
bugfix, though.




More information about the libvir-list mailing list