[libvirt] [PATCH] qemu: fix a bug in numatune (was Re: [PATCH] qemu: Prevent crash of libvirtd when setting numa parameters)

Alex Jia ajia at redhat.com
Wed Jan 4 09:56:21 UTC 2012


On 01/04/2012 05:28 PM, Hu Tao wrote:
> On Wed, Jan 04, 2012 at 05:15:24PM +0800, Alex Jia wrote:
>> On 01/04/2012 05:04 PM, Hu Tao wrote:
>>> On Wed, Jan 04, 2012 at 03:53:19PM +0800, ajia at redhat.com wrote:
>>>> From: Alex Jia<ajia at redhat.com>
>>>>
>>>> It's a NULL pointer deref issue, which leads to libvirtd crash. This patch
>>>> directly use 'params[i].value.s' value instead of derefing a NULL pointer
>>>> on memcpy.
>>>>
>>>> * how to reproduce?
>>>> % virsh numatune<domain>   --nodeset 0
>>> The domain must have no nodeset set previously (to crash in this example).
>>>
>>>> % service libvirtd status
>>>>
>>>> * src/qemu/qemu_driver.c (qemuDomainSetNumaParameters): avoid a NULL pointer deref.
>>>>
>>>> RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=771562
>>>>
>>>> Signed-off-by: Alex Jia<ajia at redhat.com>
>>>> ---
>>>>   src/qemu/qemu_driver.c |    6 ++----
>>>>   1 files changed, 2 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>>>> index 82bab67..1bd93f6 100644
>>>> --- a/src/qemu/qemu_driver.c
>>>> +++ b/src/qemu/qemu_driver.c
>>>> @@ -6721,14 +6721,12 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
>>>>               }
>>>>
>>>>               if (flags&   VIR_DOMAIN_AFFECT_CONFIG) {
>>>> -                memcpy(oldnodemask, persistentDef->numatune.memory.nodemask,
>>>> -                       VIR_DOMAIN_CPUMASK_LEN);
>>>> +                memcpy(oldnodemask, params[i].value.s, VIR_DOMAIN_CPUMASK_LEN);
>>>>                   if (virDomainCpuSetParse(params[i].value.s,
>>>>                                            0,
>>>>                                            persistentDef->numatune.memory.nodemask,
>>> Not correct. In this case persistentDef->numatune.memory.nodemask is
>>> null, and virDomainCpuSetParse will always fail, thus the nodeset will
>>> never be set.
>> In fact, I can successfully set nodeset value:
>>
>> # virsh numatune foo --nodeset 0-1
>>
>> # virsh numatune foo
>> numa_mode      : strict
>> numa_nodeset   : 0-1
> Weird. I've never succeeded with your patch. Can you double-check again?
Hu Tao, Indeed, it's weird. the patch always works well for me:

# for i in $(seq 10); do virsh numatune foo --nodeset 0-$i; virsh 
numatune foo; done

numa_mode      : strict
numa_nodeset   : 0-1


numa_mode      : strict
numa_nodeset   : 0-2


numa_mode      : strict
numa_nodeset   : 0-3


numa_mode      : strict
numa_nodeset   : 0-4


numa_mode      : strict
numa_nodeset   : 0-5


numa_mode      : strict
numa_nodeset   : 0-6


numa_mode      : strict
numa_nodeset   : 0-7


numa_mode      : strict
numa_nodeset   : 0-8


numa_mode      : strict
numa_nodeset   : 0-9


numa_mode      : strict
numa_nodeset   : 0-10

>>>>                                            VIR_DOMAIN_CPUMASK_LEN)<   0) {
>>>> -                    memcpy(persistentDef->numatune.memory.nodemask,
>>>> -                           oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
>>>> +                    memcpy(params[i].value.s, oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
>>>>                       ret = -1;
>>>>                       continue;
>>>>                   }
>>>  From f2fe7c7d0041779895330416dca6ac97fcbec88a Mon Sep 17 00:00:00 2001
>>> From: Hu Tao<hutao at cn.fujitsu.com>
>>> Date: Wed, 4 Jan 2012 17:00:27 +0800
>>> Subject: [PATCH] qemu: fix a bug in numatune
>>>
>>> When setting numa nodeset for a domain which has no nodeset set
>>> before, libvirtd crashes by dereferring the pointer to the old
>>> nodemask which is null in the case.
>>> ---
>>>   src/qemu/qemu_driver.c |   22 ++++++++++++++++++----
>>>   1 files changed, 18 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>>> index 82bab67..37330b4 100644
>>> --- a/src/qemu/qemu_driver.c
>>> +++ b/src/qemu/qemu_driver.c
>>> @@ -6721,14 +6721,28 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
>>>               }
>>>
>>>               if (flags&   VIR_DOMAIN_AFFECT_CONFIG) {
>>> -                memcpy(oldnodemask, persistentDef->numatune.memory.nodemask,
>>> -                       VIR_DOMAIN_CPUMASK_LEN);
>>> +                bool savedmask = false;
>>> +                if (!persistentDef->numatune.memory.nodemask) {
>>> +                    if (VIR_ALLOC_N(persistentDef->numatune.memory.nodemask,
>>> +                                    VIR_DOMAIN_CPUMASK_LEN)<   0) {
>>> +                        virReportOOMError();
>>> +                        ret = -1;
>>> +                        goto cleanup;
>>> +                    }
>>> +                } else {
>>> +                    memcpy(oldnodemask, persistentDef->numatune.memory.nodemask,
>>> +                           VIR_DOMAIN_CPUMASK_LEN);
>>> +                    savedmask = true;
>>> +                }
>>>                   if (virDomainCpuSetParse(params[i].value.s,
>>>                                            0,
>>>                                            persistentDef->numatune.memory.nodemask,
>>>                                            VIR_DOMAIN_CPUMASK_LEN)<   0) {
>>> -                    memcpy(persistentDef->numatune.memory.nodemask,
>>> -                           oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
>>> +                    if (savedmask)
>>> +                        memcpy(persistentDef->numatune.memory.nodemask,
>>> +                               oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
>>> +                    else
>>> +                        VIR_FREE(persistentDef->numatune.memory.nodemask);
> Oops. The same should be done when --live.
>
>>>                       ret = -1;
>>>                       continue;
>>>                   }




More information about the libvir-list mailing list