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