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

Hu Tao hutao at cn.fujitsu.com
Wed Jan 4 09:28:06 UTC 2012


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?

> >>                                           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;
> >                  }

-- 
Thanks,
Hu Tao




More information about the libvir-list mailing list