CVE-2013-6436: fix crash in lxcDomainGetMemoryParameters

The function doesn't check whether the request is made for active or
inactive domain.  Thus when the domain is not running it still tries
accessing non-existing cgroups (priv->cgroup, which is NULL).

I re-made the function in order for it to work the same way it's qemu
counterpart does.

Reproducer:
 1) Define an LXC domain
 2) Do 'virsh memtune <domain>'

Backtrace:
 Thread 6 (Thread 0x7fffec8c0700 (LWP 13387)):
 #0  0x00007ffff70edcc4 in virCgroupPathOfController (group=0x0, controller=3,
     key=0x7ffff75734bd "memory.limit_in_bytes", path=0x7fffec8bf750) at util/vircgroup.c:1764
 #1  0x00007ffff70e958c in virCgroupGetValueStr (group=0x0, controller=3,
     key=0x7ffff75734bd "memory.limit_in_bytes", value=0x7fffec8bf7c0) at util/vircgroup.c:705
 #2  0x00007ffff70e9d29 in virCgroupGetValueU64 (group=0x0, controller=3,
     key=0x7ffff75734bd "memory.limit_in_bytes", value=0x7fffec8bf810) at util/vircgroup.c:804
 #3  0x00007ffff70ee706 in virCgroupGetMemoryHardLimit (group=0x0, kb=0x7fffec8bf8a8)
     at util/vircgroup.c:1962
 #4  0x00005555557d590f in lxcDomainGetMemoryParameters (dom=0x7fffd40024a0,
     params=0x7fffd40027a0, nparams=0x7fffec8bfa24, flags=0) at lxc/lxc_driver.c:826
 #5  0x00007ffff72c28d3 in virDomainGetMemoryParameters (domain=0x7fffd40024a0,
     params=0x7fffd40027a0, nparams=0x7fffec8bfa24, flags=0) at libvirt.c:4137
 #6  0x000055555563714d in remoteDispatchDomainGetMemoryParameters (server=0x555555eb7e00,
     client=0x555555ebaef0, msg=0x555555ebb3e0, rerr=0x7fffec8bfb70, args=0x7fffd40024e0,
     ret=0x7fffd4002420) at remote.c:1895
 #7  0x00005555556052c4 in remoteDispatchDomainGetMemoryParametersHelper (server=0x555555eb7e00,
     client=0x555555ebaef0, msg=0x555555ebb3e0, rerr=0x7fffec8bfb70, args=0x7fffd40024e0,
     ret=0x7fffd4002420) at remote_dispatch.h:4050
 #8  0x00007ffff73b293f in virNetServerProgramDispatchCall (prog=0x555555ec3ae0,
     server=0x555555eb7e00, client=0x555555ebaef0, msg=0x555555ebb3e0)
     at rpc/virnetserverprogram.c:435
 #9  0x00007ffff73b207f in virNetServerProgramDispatch (prog=0x555555ec3ae0,
     server=0x555555eb7e00, client=0x555555ebaef0, msg=0x555555ebb3e0)
     at rpc/virnetserverprogram.c:305
 #10 0x00007ffff73a4d2c in virNetServerProcessMsg (srv=0x555555eb7e00, client=0x555555ebaef0,
     prog=0x555555ec3ae0, msg=0x555555ebb3e0) at rpc/virnetserver.c:165
 #11 0x00007ffff73a4e8d in virNetServerHandleJob (jobOpaque=0x555555ebc7e0, opaque=0x555555eb7e00)
     at rpc/virnetserver.c:186
 #12 0x00007ffff7187f3f in virThreadPoolWorker (opaque=0x555555eb7ac0) at util/virthreadpool.c:144
 #13 0x00007ffff718733a in virThreadHelper (data=0x555555eb7890) at util/virthreadpthread.c:161
 #14 0x00007ffff468ed89 in start_thread (arg=0x7fffec8c0700) at pthread_create.c:308
 #15 0x00007ffff3da26bd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit f8c1cb90213508c4f32549023b0572ed774e48aa)

Conflicts:
	src/lxc/lxc_driver.c
This commit is contained in:
Martin Kletzander 2013-12-09 11:15:11 +01:00 committed by Daniel P. Berrange
parent d3334a534f
commit 30a589bc47

View File

@ -884,15 +884,17 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
int *nparams,
unsigned int flags)
{
virLXCDriverPtr driver = dom->conn->privateData;
int i;
virDomainDefPtr vmdef = NULL;
virDomainObjPtr vm = NULL;
virLXCDomainObjPrivatePtr priv = NULL;
virLXCDriverPtr driver = dom->conn->privateData;
unsigned long long val;
int ret = -1;
int rc;
virLXCDomainObjPrivatePtr priv;
int i;
virCheckFlags(0, -1);
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
lxcDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
@ -906,9 +908,18 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
}
priv = vm->privateData;
if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0)
if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0 ||
virDomainLiveConfigHelperMethod(driver->caps, driver->xmlopt,
vm, &flags, &vmdef) < 0)
goto cleanup;
if (flags & VIR_DOMAIN_AFFECT_LIVE &&
!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("cgroup memory controller is not mounted"));
goto cleanup;
}
if ((*nparams) == 0) {
/* Current number of memory parameters supported by cgroups */
*nparams = LXC_NB_MEM_PARAM;
@ -922,8 +933,10 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
switch (i) {
case 0: /* fill memory hard limit here */
rc = virCgroupGetMemoryHardLimit(priv->cgroup, &val);
if (rc != 0) {
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
val = vmdef->mem.hard_limit;
val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
} else if ((rc = virCgroupGetMemoryHardLimit(priv->cgroup, &val)) != 0) {
virReportSystemError(-rc, "%s",
_("unable to get memory hard limit"));
goto cleanup;
@ -933,8 +946,10 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
goto cleanup;
break;
case 1: /* fill memory soft limit here */
rc = virCgroupGetMemorySoftLimit(priv->cgroup, &val);
if (rc != 0) {
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
val = vmdef->mem.soft_limit;
val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
} else if ((rc = virCgroupGetMemorySoftLimit(priv->cgroup, &val)) != 0) {
virReportSystemError(-rc, "%s",
_("unable to get memory soft limit"));
goto cleanup;
@ -944,8 +959,10 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
goto cleanup;
break;
case 2: /* fill swap hard limit here */
rc = virCgroupGetMemSwapHardLimit(priv->cgroup, &val);
if (rc != 0) {
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
val = vmdef->mem.swap_hard_limit;
val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
} else if ((rc = virCgroupGetMemSwapHardLimit(priv->cgroup, &val)) < 0) {
virReportSystemError(-rc, "%s",
_("unable to get swap hard limit"));
goto cleanup;