[libvirt] [PATCH v2 2/4] security: introduce virSecurityManagerCheckAllLabel function

Erik Skultety eskultet at redhat.com
Tue Feb 10 16:17:34 UTC 2015


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




More information about the libvir-list mailing list