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/qemu/qemu_process.c | 6 ++ src/security/security_manager.c | 126 ++++++++++++++++++++++++++++++++++++++++ src/security/security_manager.h | 2 + 4 files changed, 135 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3b4ff41..1b1d891 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -953,6 +953,7 @@ virSecurityDriverLookup; # security/security_manager.h +virSecurityManagerCheckAllLabel; virSecurityManagerClearSocketLabel; virSecurityManagerGenLabel; virSecurityManagerGetBaseLabel; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d5df60d..66ae779 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4428,6 +4428,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)"); @@ -5424,6 +5428,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 000bc82..32bc9fe 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -685,6 +685,132 @@ virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr, } +static int +virSecurityManagerCheckSecurityDiskLabel(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk, + void *opaque) +{ + size_t i, j; + virSecurityManagerPtr mgr = opaque; + virSecurityManagerPtr *sec_managers = NULL; + + if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL) + return 0; + + for (i = 0; i < disk->src->nseclabels; i++) { + if (STREQ_NULLABLE(disk->src->seclabels[i]->model, "none")) + continue; + + for (j = 0; sec_managers[j]; j++) { + if (STREQ_NULLABLE(disk->src->seclabels[i]->model, + sec_managers[j]->drv->name)) { + break; + } + } + if (!sec_managers[j]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unable to find security driver for model %s"), + disk->src->seclabels[i]->model); + return -1; + } + } + + return 0; +} + + +static int +virSecurityManagerCheckSecurityChardevLabel(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainChrDefPtr chrdev, + void *opaque) +{ + size_t i, j; + virSecurityManagerPtr mgr = opaque; + virSecurityManagerPtr *sec_managers = NULL; + + if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL) + return 0; + + for (i = 0; i < chrdev->nseclabels; i++) { + if (STREQ_NULLABLE(chrdev->seclabels[i]->model, "none")) + continue; + + for (j = 0; sec_managers[j]; j++) { + if (STREQ_NULLABLE(chrdev->seclabels[i]->model, + sec_managers[j]->drv->name)) { + break; + } + } + if (!sec_managers[j]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unable to find security driver for model %s"), + chrdev->seclabels[i]->model); + return -1; + } + } + + return 0; +} + + +static int +virSecurityManagerCheckSecurityChardevCallback(virDomainDefPtr def, + virDomainChrDefPtr dev, + void *opaque) +{ + return virSecurityManagerCheckSecurityChardevLabel(def, dev, opaque); +} + + +int virSecurityManagerCheckAllLabel(virSecurityManagerPtr mgr, + virDomainDefPtr vm) +{ + size_t i, j; + virSecurityManagerPtr *sec_managers = NULL; + + if (mgr == NULL || mgr->drv == NULL) + return 0; + + if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL) + return 0; + + /* first check per-domain seclabels */ + for (i = 0; i < vm->nseclabels; i++) { + if (STREQ_NULLABLE(vm->seclabels[i]->model, "none")) + continue; + + for (j = 0; sec_managers[j]; j++) { + if (STREQ_NULLABLE(vm->seclabels[i]->model, + sec_managers[j]->drv->name)) { + break; + } + } + if (!sec_managers[j]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unable to find security driver for model %s"), + vm->seclabels[i]->model); + return -1; + } + } + + /* second check per-device seclabels */ + for (i = 0; i < vm->ndisks; i++) { + if (virSecurityManagerCheckSecurityDiskLabel(vm, + 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