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 <source> 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 --- src/libvirt_private.syms | 1 + src/lxc/lxc_process.c | 3 ++ src/qemu/qemu_process.c | 6 +++ src/security/security_manager.c | 89 +++++++++++++++++++++++++++++++++++++++++ src/security/security_manager.h | 2 + 5 files changed, 101 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 645aef1..e98e813 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -955,6 +955,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 19ea7f3..52b7f41 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 43a64a1..1d4e957 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 302f54d..68ed85b 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -703,6 +703,95 @@ virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr, } +static int virSecurityManagerCheckSecurityModel(char *secmodel, + void *opaque) +{ + size_t i; + virSecurityManagerPtr mgr = opaque; + 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 +virSecurityManagerCheckSecurityDiskLabel(virDomainDiskDefPtr disk, + void *opaque) +{ + size_t i; + + for (i = 0; i < disk->src->nseclabels; i++) { + if (virSecurityManagerCheckSecurityModel(disk->src->seclabels[i]->model, + opaque) < 0) + return -1; + } + + return 0; +} + + +static int +virSecurityManagerCheckSecurityChardevLabel(virDomainChrDefPtr dev, + void *opaque) +{ + size_t i; + + for (i = 0; i < dev->nseclabels; i++) { + if (virSecurityManagerCheckSecurityModel(dev->seclabels[i]->model, + opaque) < 0) + return -1; + } + + return 0; +} + + +static int +virSecurityManagerCheckSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainChrDefPtr dev, + void *opaque) +{ + return virSecurityManagerCheckSecurityChardevLabel(dev, opaque); +} + + +int virSecurityManagerCheckAllLabel(virSecurityManagerPtr mgr, + virDomainDefPtr vm) +{ + size_t i; + + for (i = 0; i < vm->ndisks; i++) { + if (virSecurityManagerCheckSecurityDiskLabel(vm->disks[i], + mgr) < 0) + return -1; + } + + if (virDomainChrDefForeach(vm, + true, + virSecurityManagerCheckSecurityChardevCallback, + 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 156f882..13468db 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); -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list