mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-09 14:35:25 +00:00
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 f8c1cb9021
)
This commit is contained in:
parent
b861c09a1d
commit
7938401848
@ -795,22 +795,36 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
|
|||||||
int *nparams,
|
int *nparams,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
size_t i;
|
virCapsPtr caps = NULL;
|
||||||
|
virDomainDefPtr vmdef = NULL;
|
||||||
virDomainObjPtr vm = NULL;
|
virDomainObjPtr vm = NULL;
|
||||||
|
virLXCDomainObjPrivatePtr priv = NULL;
|
||||||
|
virLXCDriverPtr driver = dom->conn->privateData;
|
||||||
unsigned long long val;
|
unsigned long long val;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virLXCDomainObjPrivatePtr priv;
|
size_t i;
|
||||||
|
|
||||||
virCheckFlags(0, -1);
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
||||||
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
||||||
|
|
||||||
if (!(vm = lxcDomObjFromDomain(dom)))
|
if (!(vm = lxcDomObjFromDomain(dom)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
priv = vm->privateData;
|
priv = vm->privateData;
|
||||||
|
|
||||||
if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0)
|
if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0 ||
|
||||||
|
!(caps = virLXCDriverGetCapabilities(driver, false)) ||
|
||||||
|
virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
|
||||||
|
vm, &flags, &vmdef) < 0)
|
||||||
goto cleanup;
|
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) {
|
if ((*nparams) == 0) {
|
||||||
/* Current number of memory parameters supported by cgroups */
|
/* Current number of memory parameters supported by cgroups */
|
||||||
*nparams = LXC_NB_MEM_PARAM;
|
*nparams = LXC_NB_MEM_PARAM;
|
||||||
@ -824,22 +838,34 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
|
|||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: /* fill memory hard limit here */
|
case 0: /* fill memory hard limit here */
|
||||||
if (virCgroupGetMemoryHardLimit(priv->cgroup, &val) < 0)
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
||||||
|
val = vmdef->mem.hard_limit;
|
||||||
|
val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
|
||||||
|
} else if (virCgroupGetMemoryHardLimit(priv->cgroup, &val) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
|
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
|
||||||
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 1: /* fill memory soft limit here */
|
case 1: /* fill memory soft limit here */
|
||||||
if (virCgroupGetMemorySoftLimit(priv->cgroup, &val) < 0)
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
||||||
|
val = vmdef->mem.soft_limit;
|
||||||
|
val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
|
||||||
|
} else if (virCgroupGetMemorySoftLimit(priv->cgroup, &val) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
|
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
|
||||||
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 2: /* fill swap hard limit here */
|
case 2: /* fill swap hard limit here */
|
||||||
if (virCgroupGetMemSwapHardLimit(priv->cgroup, &val) < 0)
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
||||||
|
val = vmdef->mem.swap_hard_limit;
|
||||||
|
val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
|
||||||
|
} else if (virCgroupGetMemSwapHardLimit(priv->cgroup, &val) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
if (virTypedParameterAssign(param,
|
if (virTypedParameterAssign(param,
|
||||||
VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
|
VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
|
||||||
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
||||||
@ -860,6 +886,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
|
|||||||
cleanup:
|
cleanup:
|
||||||
if (vm)
|
if (vm)
|
||||||
virObjectUnlock(vm);
|
virObjectUnlock(vm);
|
||||||
|
virObjectUnref(caps);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user