From c3d9d3bbc99b6694b713f6de4198e285ba944f03 Mon Sep 17 00:00:00 2001 From: Erik Skultety Date: Thu, 12 Feb 2015 18:32:40 +0100 Subject: [PATCH] security: introduce virSecurityManagerCheckAllLabel function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do have a check for valid per-domain security model, however we still do permit an invalid security model for a domain's device (those which are specified with element). This patch introduces a new function virSecurityManagerCheckAllLabel which compares user specified security model against currently registered security drivers. That being said, it also permits 'none' being specified as a device security model. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1165485 Signed-off-by: Ján Tomko --- src/libvirt_private.syms | 1 + src/lxc/lxc_process.c | 3 ++ src/qemu/qemu_process.c | 6 +++ src/security/security_manager.c | 84 +++++++++++++++++++++++++++++++++ src/security/security_manager.h | 2 + 5 files changed, 96 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a241d5153b..c07a5613f1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -956,6 +956,7 @@ virSecurityDriverLookup; # security/security_manager.h +virSecurityManagerCheckAllLabel; virSecurityManagerClearSocketLabel; virSecurityManagerGenLabel; virSecurityManagerGetBaseLabel; diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 19ea7f314f..52b7f41357 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -1135,6 +1135,9 @@ int virLXCProcessStart(virConnectPtr conn, vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT) vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE; + if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0) + goto cleanup; + if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) { virDomainAuditSecurityLabel(vm, false); goto cleanup; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 43a64a16b2..1d4e957729 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4488,6 +4488,10 @@ int qemuProcessStart(virConnectPtr conn, NULL) < 0) goto cleanup; + VIR_DEBUG("Checking domain and device security labels"); + if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0) + goto cleanup; + /* If you are using a SecurityDriver with dynamic labelling, then generate a security label for isolation */ VIR_DEBUG("Generating domain security label (if required)"); @@ -5488,6 +5492,8 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, } } + if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0) + goto error; if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) goto error; diff --git a/src/security/security_manager.c b/src/security/security_manager.c index 302f54d2b3..4b5132f8d0 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -703,6 +703,90 @@ virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr, } +static int virSecurityManagerCheckModel(virSecurityManagerPtr mgr, + char *secmodel) +{ + size_t i; + virSecurityManagerPtr *sec_managers = NULL; + + if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL) + return -1; + + if (STREQ_NULLABLE(secmodel, "none")) + return 0; + + for (i = 0; sec_managers[i]; i++) { + if (STREQ_NULLABLE(secmodel, sec_managers[i]->drv->name)) + return 0; + } + + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unable to find security driver for model %s"), + secmodel); + return -1; +} + + +static int +virSecurityManagerCheckDiskLabel(virSecurityManagerPtr mgr, + virDomainDiskDefPtr disk) +{ + size_t i; + + for (i = 0; i < disk->src->nseclabels; i++) { + if (virSecurityManagerCheckModel(mgr, disk->src->seclabels[i]->model) < 0) + return -1; + } + + return 0; +} + + +static int +virSecurityManagerCheckChardevLabel(virSecurityManagerPtr mgr, + virDomainChrDefPtr dev) +{ + size_t i; + + for (i = 0; i < dev->nseclabels; i++) { + if (virSecurityManagerCheckModel(mgr, dev->seclabels[i]->model) < 0) + return -1; + } + + return 0; +} + + +static int +virSecurityManagerCheckChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainChrDefPtr dev, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + return virSecurityManagerCheckChardevLabel(mgr, dev); +} + + +int virSecurityManagerCheckAllLabel(virSecurityManagerPtr mgr, + virDomainDefPtr vm) +{ + size_t i; + + for (i = 0; i < vm->ndisks; i++) { + if (virSecurityManagerCheckDiskLabel(mgr, vm->disks[i]) < 0) + return -1; + } + + if (virDomainChrDefForeach(vm, + true, + virSecurityManagerCheckChardevCallback, + mgr) < 0) + return -1; + + return 0; +} + + int virSecurityManagerSetAllLabel(virSecurityManagerPtr mgr, virDomainDefPtr vm, diff --git a/src/security/security_manager.h b/src/security/security_manager.h index 156f882910..13468db399 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -111,6 +111,8 @@ int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr, pid_t pid); int virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr, virDomainDefPtr sec); +int virSecurityManagerCheckAllLabel(virSecurityManagerPtr mgr, + virDomainDefPtr sec); int virSecurityManagerSetAllLabel(virSecurityManagerPtr mgr, virDomainDefPtr sec, const char *stdin_path);