]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Update security layer to handle many security labels
authorMarcelo Cerri <mhcerri@linux.vnet.ibm.com>
Wed, 15 Aug 2012 22:10:37 +0000 (19:10 -0300)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 20 Aug 2012 17:14:30 +0000 (19:14 +0200)
These changes make the security drivers able to find and handle the
correct security label information when more than one label is
available. They also update the DAC driver to be used as an usual
security driver.

Signed-off-by: Marcelo Cerri <mhcerri@linux.vnet.ibm.com>
src/libvirt_private.syms
src/qemu/qemu_driver.c
src/qemu/qemu_process.c
src/security/security_apparmor.c
src/security/security_dac.c
src/security/security_manager.c
src/security/security_manager.h
src/security/security_selinux.c
src/security/security_stack.c
src/security/security_stack.h

index 4d28607ff8848e675733ca4e07873e332bb552cf..a55fb73e7223163dd5bc9d1e6b6efb507872f10e 100644 (file)
@@ -992,6 +992,7 @@ virSecurityManagerFree;
 virSecurityManagerGenLabel;
 virSecurityManagerGetDOI;
 virSecurityManagerGetModel;
+virSecurityManagerGetNested;
 virSecurityManagerGetProcessLabel;
 virSecurityManagerNew;
 virSecurityManagerNewStack;
@@ -1010,6 +1011,7 @@ virSecurityManagerSetHostdevLabel;
 virSecurityManagerSetProcessLabel;
 virSecurityManagerSetSavedStateLabel;
 virSecurityManagerSetSocketLabel;
+virSecurityManagerStackAddNested;
 virSecurityManagerVerify;
 virSecurityManagerGetMountOptions;
 
index 6a43bb9d955d14ea1110a3e683cb800a84e2eea7..9f1d70b0ddf392334ff01fc928bb6ae5fda0be17 100644 (file)
@@ -268,8 +268,8 @@ qemuSecurityInit(struct qemud_driver *driver)
         if (!dac)
             goto error;
 
-        if (!(driver->securityManager = virSecurityManagerNewStack(mgr,
-                                                                   dac))) {
+        if (!(driver->securityManager = virSecurityManagerNewStack(mgr)) ||
+            !(virSecurityManagerStackAddNested(mgr, dac))) {
 
             virSecurityManagerFree(dac);
             goto error;
@@ -291,7 +291,11 @@ static virCapsPtr
 qemuCreateCapabilities(virCapsPtr oldcaps,
                        struct qemud_driver *driver)
 {
+    size_t i;
     virCapsPtr caps;
+    virSecurityManagerPtr *sec_managers = NULL;
+    /* Security driver data */
+    const char *doi, *model;
 
     /* Basic host arch / guest machine capabilities */
     if (!(caps = qemuCapsInit(oldcaps))) {
@@ -316,31 +320,38 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
         goto err_exit;
     }
 
-    /* Security driver data */
-    const char *doi, *model;
+    /* access sec drivers and create a sec model for each one */
+    sec_managers = virSecurityManagerGetNested(driver->securityManager);
+    if (sec_managers == NULL) {
+        goto err_exit;
+    }
 
-    doi = virSecurityManagerGetDOI(driver->securityManager);
-    model = virSecurityManagerGetModel(driver->securityManager);
+    /* calculate length */
+    for (i = 0; sec_managers[i]; i++)
+        ;
+    caps->host.nsecModels = i;
 
-    if (VIR_ALLOC(caps->host.secModels) < 0) {
+    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
         goto no_memory;
-    }
 
-    if (STRNEQ(model, "none")) {
-        if (!(caps->host.secModels[0].model = strdup(model)))
+    for (i = 0; sec_managers[i]; i++) {
+        doi = virSecurityManagerGetDOI(sec_managers[i]);
+        model = virSecurityManagerGetModel(sec_managers[i]);
+        if (!(caps->host.secModels[i].model = strdup(model)))
             goto no_memory;
-        if (!(caps->host.secModels[0].doi = strdup(doi)))
+        if (!(caps->host.secModels[i].doi = strdup(doi)))
             goto no_memory;
+        VIR_DEBUG("Initialized caps for security driver \"%s\" with "
+                  "DOI \"%s\"", model, doi);
     }
-
-    VIR_DEBUG("Initialized caps for security driver \"%s\" with "
-              "DOI \"%s\"", model, doi);
+    VIR_FREE(sec_managers);
 
     return caps;
 
 no_memory:
     virReportOOMError();
 err_exit:
+    VIR_FREE(sec_managers);
     virCapabilitiesFree(caps);
     return NULL;
 }
@@ -4063,9 +4074,9 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn,
     qemuDriverLock(driver);
     memset(secmodel, 0, sizeof(*secmodel));
 
-    /* NULL indicates no driver, which we treat as
-     * success, but simply return no data in *secmodel */
-    if (driver->caps->host.secModels[0].model == NULL)
+    /* We treat no driver as success, but simply return no data in *secmodel */
+    if (driver->caps->host.nsecModels == 0 ||
+        driver->caps->host.secModels[0].model == NULL)
         goto cleanup;
 
     p = driver->caps->host.secModels[0].model;
index 553bf906524f9c1561a4a05413c6ee5dfc5ee9d4..8a9f995918ccedafc106c8d17ab84be9aeefc7f2 100644 (file)
@@ -4079,12 +4079,12 @@ void qemuProcessStop(struct qemud_driver *driver,
     virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
 
     /* Clear out dynamically assigned labels */
-    if (vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
-        if (!vm->def->seclabels[0]->baselabel)
-            VIR_FREE(vm->def->seclabels[0]->model);
-        VIR_FREE(vm->def->seclabels[0]->label);
+    for (i = 0; i < vm->def->nseclabels; i++) {
+        if (vm->def->seclabels[i]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+            VIR_FREE(vm->def->seclabels[i]->label);
+        }
+        VIR_FREE(vm->def->seclabels[i]->imagelabel);
     }
-    VIR_FREE(vm->def->seclabels[0]->imagelabel);
 
     virDomainDefClearDeviceAliases(vm->def);
     if (!priv->persistentAddrs) {
@@ -4188,6 +4188,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
                       virDomainChrSourceDefPtr monConfig,
                       bool monJSON)
 {
+    size_t i;
     char ebuf[1024];
     int logfile = -1;
     char *timestamp;
@@ -4195,6 +4196,9 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
     bool running = true;
     virDomainPausedReason reason;
     virSecurityLabelPtr seclabel = NULL;
+    virSecurityLabelDefPtr seclabeldef = NULL;
+    virSecurityManagerPtr* sec_managers = NULL;
+    const char *model;
 
     VIR_DEBUG("Beginning VM attach process");
 
@@ -4227,17 +4231,31 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
         goto no_memory;
 
     VIR_DEBUG("Detect security driver config");
-    vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_STATIC;
-    if (VIR_ALLOC(seclabel) < 0)
-        goto no_memory;
-    if (virSecurityManagerGetProcessLabel(driver->securityManager,
-                                          vm->def, vm->pid, seclabel) < 0)
+    sec_managers = virSecurityManagerGetNested(driver->securityManager);
+    if (sec_managers == NULL) {
         goto cleanup;
-    if (driver->caps->host.secModels[0].model &&
-        !(vm->def->seclabels[0]->model = strdup(driver->caps->host.secModels[0].model)))
-        goto no_memory;
-    if (!(vm->def->seclabels[0]->label = strdup(seclabel->label)))
-        goto no_memory;
+    }
+
+    for (i = 0; sec_managers[i]; i++) {
+        model = virSecurityManagerGetModel(sec_managers[i]);
+        seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model);
+        if (seclabeldef == NULL) {
+            goto cleanup;
+        }
+        seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC;
+        if (VIR_ALLOC(seclabel) < 0)
+            goto no_memory;
+        if (virSecurityManagerGetProcessLabel(driver->securityManager,
+                                              vm->def, vm->pid, seclabel) < 0)
+            goto cleanup;
+
+        if (!(seclabeldef->model = strdup(model)))
+            goto no_memory;
+
+        if (!(seclabeldef->label = strdup(seclabel->label)))
+            goto no_memory;
+        VIR_FREE(seclabel);
+    }
 
     VIR_DEBUG("Creating domain log file");
     if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
@@ -4362,6 +4380,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
 
     VIR_FORCE_CLOSE(logfile);
     VIR_FREE(seclabel);
+    VIR_FREE(sec_managers);
 
     return 0;
 
@@ -4373,6 +4392,7 @@ cleanup:
      * pretend we never started it */
     VIR_FORCE_CLOSE(logfile);
     VIR_FREE(seclabel);
+    VIR_FREE(sec_managers);
     virDomainChrSourceDefFree(monConfig);
     return -1;
 }
index 338523276048253f63ab188dc939cc713de2cdd6..299bba6d324b1ce1c30a6edde410957ab0aee171 100644 (file)
@@ -272,9 +272,13 @@ reload_profile(virSecurityManagerPtr mgr,
                const char *fn,
                bool append)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
     int rc = -1;
     char *profile_name = NULL;
+    const virSecurityLabelDefPtr secdef = virDomainDefGetSecurityLabelDef(
+                                                def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return rc;
 
     if (secdef->norelabel)
         return 0;
@@ -308,10 +312,14 @@ AppArmorSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
     virDomainDefPtr def = ptr->def;
 
     if (reload_profile(ptr->mgr, def, file, true) < 0) {
-        const virSecurityLabelDefPtr secdef = &def->seclabel;
+        const virSecurityLabelDefPtr secdef = virDomainDefGetSecurityLabelDef(
+                                                def, SECURITY_APPARMOR_NAME);
+        if (!secdef) {
+            virReportOOMError();
+            return -1;
+        }
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot update AppArmor profile "
-                         "\'%s\'"),
+                       _("cannot update AppArmor profile \'%s\'"),
                        secdef->imagelabel);
         return -1;
     }
@@ -326,10 +334,14 @@ AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
     virDomainDefPtr def = ptr->def;
 
     if (reload_profile(ptr->mgr, def, file, true) < 0) {
-        const virSecurityLabelDefPtr secdef = &def->seclabel;
+        const virSecurityLabelDefPtr secdef = virDomainDefGetSecurityLabelDef(
+                                                def, SECURITY_APPARMOR_NAME);
+        if (!secdef) {
+            virReportOOMError();
+            return -1;
+        }
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot update AppArmor profile "
-                         "\'%s\'"),
+                       _("cannot update AppArmor profile \'%s\'"),
                        secdef->imagelabel);
         return -1;
     }
@@ -408,18 +420,23 @@ AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
 {
     int rc = -1;
     char *profile_name = NULL;
+    virSecurityLabelDefPtr secdef = virDomainDefGetSecurityLabelDef(def,
+                                                SECURITY_APPARMOR_NAME);
 
-    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
+    if (!secdef)
+        return -1;
+
+    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
 
-    if (def->seclabel.baselabel) {
+    if (secdef->baselabel) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        "%s", _("Cannot set a base label with AppArmour"));
         return rc;
     }
 
-    if ((def->seclabel.label) ||
-        (def->seclabel.model) || (def->seclabel.imagelabel)) {
+    if ((secdef->label) ||
+        (secdef->model) || (secdef->imagelabel)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s",
                        _("security label already defined for VM"));
@@ -429,31 +446,31 @@ AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
     if ((profile_name = get_profile_name(def)) == NULL)
         return rc;
 
-    def->seclabel.label = strndup(profile_name, strlen(profile_name));
-    if (!def->seclabel.label) {
+    secdef->label = strndup(profile_name, strlen(profile_name));
+    if (!secdef->label) {
         virReportOOMError();
         goto clean;
     }
 
     /* set imagelabel the same as label (but we won't use it) */
-    def->seclabel.imagelabel = strndup(profile_name,
-                                           strlen(profile_name));
-    if (!def->seclabel.imagelabel) {
+    secdef->imagelabel = strndup(profile_name,
+                                 strlen(profile_name));
+    if (!secdef->imagelabel) {
         virReportOOMError();
         goto err;
     }
 
-    def->seclabel.model = strdup(SECURITY_APPARMOR_NAME);
-    if (!def->seclabel.model) {
+    secdef->model = strdup(SECURITY_APPARMOR_NAME);
+    if (!secdef->model) {
         virReportOOMError();
         goto err;
     }
 
     /* Now that we have a label, load the profile into the kernel. */
-    if (load_profile(mgr, def->seclabel.label, def, NULL, false) < 0) {
+    if (load_profile(mgr, secdef->label, def, NULL, false) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot load AppArmor profile "
-                         "\'%s\'"), def->seclabel.label);
+                       "\'%s\'"), secdef->label);
         goto err;
     }
 
@@ -461,9 +478,9 @@ AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
     goto clean;
 
   err:
-    VIR_FREE(def->seclabel.label);
-    VIR_FREE(def->seclabel.imagelabel);
-    VIR_FREE(def->seclabel.model);
+    VIR_FREE(secdef->label);
+    VIR_FREE(secdef->imagelabel);
+    VIR_FREE(secdef->model);
 
   clean:
     VIR_FREE(profile_name);
@@ -475,7 +492,12 @@ static int
 AppArmorSetSecurityAllLabel(virSecurityManagerPtr mgr,
                             virDomainDefPtr def, const char *stdin_path)
 {
-    if (def->seclabel.norelabel)
+    virSecurityLabelDefPtr secdef = virDomainDefGetSecurityLabelDef(def,
+                                                    SECURITY_APPARMOR_NAME);
+    if (!secdef)
+        return -1;
+
+    if (secdef->norelabel)
         return 0;
 
     /* Reload the profile if stdin_path is specified. Note that
@@ -528,7 +550,10 @@ static int
 AppArmorReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    const virSecurityLabelDefPtr secdef = virDomainDefGetSecurityLabelDef(def,
+                                                        SECURITY_APPARMOR_NAME);
+    if (!secdef)
+        return -1;
 
     VIR_FREE(secdef->model);
     VIR_FREE(secdef->label);
@@ -543,8 +568,12 @@ AppArmorRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                 virDomainDefPtr def,
                                 int migrated ATTRIBUTE_UNUSED)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
     int rc = 0;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
 
     if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
         if ((rc = remove_profile(secdef->label)) != 0) {
@@ -562,9 +591,13 @@ AppArmorRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
 static int
 AppArmorSetSecurityProcessLabel(virSecurityManagerPtr mgr, virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
     int rc = -1;
     char *profile_name = NULL;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
 
     if ((profile_name = get_profile_name(def)) == NULL)
         return rc;
@@ -631,9 +664,13 @@ static int
 AppArmorSetSecurityImageLabel(virSecurityManagerPtr mgr,
                               virDomainDefPtr def, virDomainDiskDefPtr disk)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
     int rc = -1;
     char *profile_name;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -676,7 +713,11 @@ static int
 AppArmorSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                        virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
 
     if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
         if (use_apparmor() < 0 || profile_status(secdef->label, 0) < 0) {
@@ -704,9 +745,13 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
                                 virDomainHostdevDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
     struct SDPDOP *ptr;
     int ret = -1;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -766,7 +811,12 @@ AppArmorRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
                                     virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
 
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -799,7 +849,11 @@ AppArmorSetImageFDLabel(virSecurityManagerPtr mgr,
     char *proc = NULL;
     char *fd_path = NULL;
 
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    const virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return -1;
 
     if (secdef->imagelabel == NULL)
         return 0;
index f398c3fa68538a6d3533ca4dd58c34b0036af643..e37b09e2a7d6bb452011cf6c43d49969ef267b44 100644 (file)
@@ -33,6 +33,7 @@
 #include "storage_file.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
+#define SECURITY_DAC_NAME "dac"
 
 typedef struct _virSecurityDACData virSecurityDACData;
 typedef virSecurityDACData *virSecurityDACDataPtr;
@@ -64,6 +65,134 @@ void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
     priv->dynamicOwnership = dynamicOwnership;
 }
 
+static
+int parseIds(const char *label, uid_t *uidPtr, gid_t *gidPtr)
+{
+    uid_t uid;
+    gid_t gid;
+    char *endptr = NULL;
+
+    if (label == NULL)
+        return -1;
+
+    if (virStrToLong_ui(label, &endptr, 10, &uid) ||
+        endptr == NULL || *endptr != ':') {
+        return -1;
+    }
+
+    if (virStrToLong_ui(endptr + 1, NULL, 10, &gid))
+        return -1;
+
+    if (uidPtr)
+        *uidPtr = uid;
+    if (gidPtr)
+        *gidPtr = gid;
+    return 0;
+}
+
+static
+int virSecurityDACParseIds(virDomainDefPtr def, uid_t *uidPtr, gid_t *gidPtr)
+{
+    uid_t uid;
+    gid_t gid;
+    virSecurityLabelDefPtr seclabel;
+
+    if (def == NULL)
+        return -1;
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
+    if (seclabel == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("security label for DAC not found in domain %s"),
+                       def->name);
+        return -1;
+    }
+
+    if (seclabel->label && parseIds(seclabel->label, &uid, &gid)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("failed to parse uid and gid for DAC "
+                         "security driver: %s"), seclabel->label);
+        return -1;
+    }
+
+    if (uidPtr)
+        *uidPtr = uid;
+    if (gidPtr)
+        *gidPtr = gid;
+
+    return 0;
+}
+
+static
+int virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
+                         uid_t *uidPtr, gid_t *gidPtr)
+{
+    if (virSecurityDACParseIds(def, uidPtr, gidPtr) == 0)
+        return 0;
+
+    if (priv) {
+        if (uidPtr)
+            *uidPtr = priv->user;
+        if (gidPtr)
+            *gidPtr = priv->group;
+        return 0;
+    }
+    return -1;
+}
+
+static
+int virSecurityDACParseImageIds(virDomainDefPtr def,
+                                uid_t *uidPtr, gid_t *gidPtr)
+{
+    uid_t uid;
+    gid_t gid;
+    virSecurityLabelDefPtr seclabel;
+
+    if (def == NULL)
+        return -1;
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
+    if (seclabel == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("security label for DAC not found in domain %s"),
+                       def->name);
+        return -1;
+    }
+
+    if (seclabel->imagelabel
+        && parseIds(seclabel->imagelabel, &uid, &gid)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("failed to parse uid and gid for DAC "
+                         "security driver: %s"), seclabel->label);
+        return -1;
+    }
+
+    if (uidPtr)
+        *uidPtr = uid;
+    if (gidPtr)
+        *gidPtr = gid;
+
+    return 0;
+}
+
+static
+int virSecurityDACGetImageIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
+                         uid_t *uidPtr, gid_t *gidPtr)
+{
+    if (virSecurityDACParseImageIds(def, uidPtr, gidPtr) == 0)
+        return 0;
+
+    if (priv) {
+        if (uidPtr)
+            *uidPtr = priv->user;
+        if (gidPtr)
+            *gidPtr = priv->group;
+        return 0;
+    }
+    return -1;
+}
+
+
 static virSecurityDriverStatus
 virSecurityDACProbe(const char *virtDriver ATTRIBUTE_UNUSED)
 {
@@ -85,7 +214,7 @@ virSecurityDACClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
 
 static const char * virSecurityDACGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
 {
-    return "dac";
+    return SECURITY_DAC_NAME;
 }
 
 static const char * virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
@@ -167,10 +296,17 @@ virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
                                    size_t depth ATTRIBUTE_UNUSED,
                                    void *opaque)
 {
-    virSecurityManagerPtr mgr = opaque;
+    void **params = opaque;
+    virSecurityManagerPtr mgr = params[0];
+    virDomainDefPtr def = params[1];
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    uid_t user;
+    gid_t group;
+
+    if (virSecurityDACGetImageIds(def, priv, &user, &group))
+        return -1;
 
-    return virSecurityDACSetOwnership(path, priv->user, priv->group);
+    return virSecurityDACSetOwnership(path, user, group);
 }
 
 
@@ -180,6 +316,9 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                     virDomainDiskDefPtr disk)
 
 {
+    uid_t user;
+    gid_t group;
+    void *params[2];
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
 
     if (!priv->dynamicOwnership)
@@ -188,12 +327,17 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
     if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
         return 0;
 
+    if (virSecurityDACGetImageIds(def, priv, &user, &group))
+        return -1;
+
+    params[0] = mgr;
+    params[1] = def;
     return virDomainDiskDefForeachPath(disk,
                                        virSecurityManagerGetAllowDiskFormatProbing(mgr),
                                        false,
-                                       priv->user, priv->group,
+                                       user, group,
                                        virSecurityDACSetSecurityFileLabel,
-                                       mgr);
+                                       params);
 }
 
 
@@ -259,10 +403,17 @@ virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
                                   const char *file,
                                   void *opaque)
 {
-    virSecurityManagerPtr mgr = opaque;
+    void **params = opaque;
+    virSecurityManagerPtr mgr = params[0];
+    virDomainDefPtr def = params[1];
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    uid_t user;
+    gid_t group;
 
-    return virSecurityDACSetOwnership(file, priv->user, priv->group);
+    if (virSecurityDACGetIds(def, priv, &user, &group))
+        return -1;
+
+    return virSecurityDACSetOwnership(file, user, group);
 }
 
 
@@ -271,18 +422,26 @@ virSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
                                   const char *file,
                                   void *opaque)
 {
-    virSecurityManagerPtr mgr = opaque;
+    void **params = opaque;
+    virSecurityManagerPtr mgr = params[0];
+    virDomainDefPtr def = params[1];
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    uid_t user;
+    gid_t group;
 
-    return virSecurityDACSetOwnership(file, priv->user, priv->group);
+    if (virSecurityDACGetIds(def, priv, &user, &group))
+        return -1;
+
+    return virSecurityDACSetOwnership(file, user, group);
 }
 
 
 static int
 virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
-                                      virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                      virDomainDefPtr def,
                                       virDomainHostdevDefPtr dev)
 {
+    void *params[] = {mgr, def};
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int ret = -1;
 
@@ -300,7 +459,8 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
         if (!usb)
             goto done;
 
-        ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr);
+        ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel,
+                                   params);
         usbFreeDevice(usb);
         break;
     }
@@ -314,7 +474,8 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
         if (!pci)
             goto done;
 
-        ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr);
+        ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel,
+                                   params);
         pciFreeDevice(pci);
 
         break;
@@ -404,17 +565,23 @@ done:
 
 static int
 virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
+                              virDomainDefPtr def,
                               virDomainChrSourceDefPtr dev)
 
 {
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     char *in = NULL, *out = NULL;
     int ret = -1;
+    uid_t user;
+    gid_t group;
+
+    if (virSecurityDACGetIds(def, priv, &user, &group))
+        return -1;
 
     switch (dev->type) {
     case VIR_DOMAIN_CHR_TYPE_DEV:
     case VIR_DOMAIN_CHR_TYPE_FILE:
-        ret = virSecurityDACSetOwnership(dev->data.file.path, priv->user, priv->group);
+        ret = virSecurityDACSetOwnership(dev->data.file.path, user, group);
         break;
 
     case VIR_DOMAIN_CHR_TYPE_PIPE:
@@ -424,12 +591,12 @@ virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
             goto done;
         }
         if (virFileExists(in) && virFileExists(out)) {
-            if ((virSecurityDACSetOwnership(in, priv->user, priv->group) < 0) ||
-                (virSecurityDACSetOwnership(out, priv->user, priv->group) < 0)) {
+            if ((virSecurityDACSetOwnership(in, user, group) < 0) ||
+                (virSecurityDACSetOwnership(out, user, group) < 0)) {
                 goto done;
             }
         } else if (virSecurityDACSetOwnership(dev->data.file.path,
-                                              priv->user, priv->group) < 0) {
+                                              user, group) < 0) {
             goto done;
         }
         ret = 0;
@@ -554,7 +721,7 @@ virSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
 {
     virSecurityManagerPtr mgr = opaque;
 
-    return virSecurityDACSetChardevLabel(mgr, &dev->source);
+    return virSecurityDACSetChardevLabel(mgr, def, &dev->source);
 }
 
 
@@ -565,6 +732,8 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
 {
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int i;
+    uid_t user;
+    gid_t group;
 
     if (!priv->dynamicOwnership)
         return 0;
@@ -591,16 +760,15 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
                                mgr) < 0)
         return -1;
 
+    if (virSecurityDACGetImageIds(def, priv, &user, &group))
+        return -1;
+
     if (def->os.kernel &&
-        virSecurityDACSetOwnership(def->os.kernel,
-                                    priv->user,
-                                    priv->group) < 0)
+        virSecurityDACSetOwnership(def->os.kernel, user, group) < 0)
         return -1;
 
     if (def->os.initrd &&
-        virSecurityDACSetOwnership(def->os.initrd,
-                                    priv->user,
-                                    priv->group) < 0)
+        virSecurityDACSetOwnership(def->os.initrd, user, group) < 0)
         return -1;
 
     return 0;
@@ -609,12 +777,17 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
 
 static int
 virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
-                                 virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                 virDomainDefPtr def,
                                  const char *savefile)
 {
+    uid_t user;
+    gid_t group;
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
 
-    return virSecurityDACSetOwnership(savefile, priv->user, priv->group);
+    if (virSecurityDACGetImageIds(def, priv, &user, &group))
+        return -1;
+
+    return virSecurityDACSetOwnership(savefile, user, group);
 }
 
 
@@ -636,12 +809,16 @@ static int
 virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
                               virDomainDefPtr def ATTRIBUTE_UNUSED)
 {
+    uid_t user;
+    gid_t group;
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
 
-    VIR_DEBUG("Dropping privileges of DEF to %u:%u",
-              (unsigned int) priv->user, (unsigned int) priv->group);
+    if (virSecurityDACGetIds(def, priv, &user, &group))
+        return -1;
+
+    VIR_DEBUG("Dropping privileges of DEF to %u:%u", user, group);
 
-    if (virSetUIDGID(priv->user, priv->group) < 0)
+    if (virSetUIDGID(user, group) < 0)
         return -1;
 
     return 0;
@@ -656,9 +833,85 @@ virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
 }
 
 static int
-virSecurityDACGenLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
-                       virDomainDefPtr def ATTRIBUTE_UNUSED)
+virSecurityDACGenLabel(virSecurityManagerPtr mgr,
+                       virDomainDefPtr def)
 {
+    int rc = -1;
+    virSecurityLabelDefPtr seclabel;
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    if (mgr == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("invalid security driver"));
+        return rc;
+    }
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
+    if (seclabel == NULL) {
+        return rc;
+    }
+
+    if (seclabel->imagelabel) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("security image label already "
+                         "defined for VM"));
+        return rc;
+    }
+
+    if (seclabel->model
+        && STRNEQ(seclabel->model, SECURITY_DAC_NAME)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("security label model %s is not supported "
+                         "with selinux"),
+                       seclabel->model);
+            return rc;
+    }
+
+    switch(seclabel->type) {
+    case VIR_DOMAIN_SECLABEL_STATIC:
+        if (seclabel->label == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("missing label for static security "
+                             "driver in domain %s"), def->name);
+            return rc;
+        }
+        break;
+    case VIR_DOMAIN_SECLABEL_DYNAMIC:
+        if (virAsprintf(&seclabel->label, "%d:%d", priv->user, priv->group) < 0) {
+            virReportOOMError();
+            return rc;
+        }
+        if (seclabel->label == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("cannot generate dac user and group id "
+                             "for domain %s"), def->name);
+            return rc;
+        }
+        break;
+    case VIR_DOMAIN_SECLABEL_NONE:
+        /* no op */
+        break;
+    default:
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected security label type '%s'"),
+                       virDomainSeclabelTypeToString(seclabel->type));
+        return rc;
+    }
+
+    if (!seclabel->norelabel) {
+        if (seclabel->imagelabel == NULL) {
+            seclabel->imagelabel = strdup(seclabel->label);
+            if (seclabel->imagelabel == NULL) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("cannot generate dac user and group id "
+                                 "for domain %s"), def->name);
+                VIR_FREE(seclabel->label);
+                seclabel->label = NULL;
+                return rc;
+            }
+        }
+    }
+
     return 0;
 }
 
@@ -683,6 +936,15 @@ virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                               pid_t pid ATTRIBUTE_UNUSED,
                               virSecurityLabelPtr seclabel ATTRIBUTE_UNUSED)
 {
+    virSecurityLabelDefPtr secdef =
+        virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
+
+    if (!secdef || !seclabel)
+        return -1;
+
+    if (secdef->label)
+        strcpy(seclabel->label, secdef->label);
+
     return 0;
 }
 
@@ -724,7 +986,7 @@ static char *virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_U
 
 virSecurityDriver virSecurityDriverDAC = {
     .privateDataLen                     = sizeof(virSecurityDACData),
-    .name                               = "virDAC",
+    .name                               = SECURITY_DAC_NAME,
     .probe                              = virSecurityDACProbe,
     .open                               = virSecurityDACOpen,
     .close                              = virSecurityDACClose,
index 6b372b55dae442309d11cc8195f261e5744d5a1b..0e106d5fe609840b385d4d8899d165b87cf407dc 100644 (file)
@@ -68,8 +68,7 @@ static virSecurityManagerPtr virSecurityManagerNewDriver(virSecurityDriverPtr dr
     return mgr;
 }
 
-virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary,
-                                                 virSecurityManagerPtr secondary)
+virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary)
 {
     virSecurityManagerPtr mgr =
         virSecurityManagerNewDriver(&virSecurityDriverStack,
@@ -81,12 +80,19 @@ virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary,
     if (!mgr)
         return NULL;
 
-    virSecurityStackSetPrimary(mgr, primary);
-    virSecurityStackSetSecondary(mgr, secondary);
+    virSecurityStackAddPrimary(mgr, primary);
 
     return mgr;
 }
 
+int virSecurityManagerStackAddNested(virSecurityManagerPtr stack,
+                                     virSecurityManagerPtr nested)
+{
+    if (!STREQ("stack", stack->drv->name))
+        return -1;
+    return virSecurityStackAddNested(stack, nested);
+}
+
 virSecurityManagerPtr virSecurityManagerNewDAC(const char *virtDriver,
                                                uid_t user,
                                                gid_t group,
@@ -308,27 +314,52 @@ int virSecurityManagerRestoreSavedStateLabel(virSecurityManagerPtr mgr,
 int virSecurityManagerGenLabel(virSecurityManagerPtr mgr,
                                virDomainDefPtr vm)
 {
-    if (vm->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT) {
-        if (mgr->defaultConfined) {
-            vm->seclabels[0]->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
-        } else {
-            vm->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;
-            vm->seclabels[0]->norelabel = true;
-        }
-    }
+    int rc = 0;
+    size_t i;
+    virSecurityManagerPtr* sec_managers = NULL;
+    virSecurityLabelDefPtr seclabel;
 
-    if ((vm->seclabels[0]->type == VIR_DOMAIN_SECLABEL_NONE) &&
-        mgr->requireConfined) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Unconfined guests are not allowed on this host"));
+    if (mgr == NULL || mgr->drv == NULL)
+        return -1;
+
+    if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL)
         return -1;
-    }
 
-    if (mgr->drv->domainGenSecurityLabel)
-        return mgr->drv->domainGenSecurityLabel(mgr, vm);
+    for (i = 0; sec_managers[i]; i++) {
+        seclabel = virDomainDefGetSecurityLabelDef(vm,
+                                                   sec_managers[i]->drv->name);
+        if (seclabel == NULL) {
+            rc = -1;
+            goto cleanup;
+        }
 
-    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
+        if (seclabel->type == VIR_DOMAIN_SECLABEL_DEFAULT) {
+            if (sec_managers[i]->defaultConfined)
+                seclabel->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
+            else
+                seclabel->type = VIR_DOMAIN_SECLABEL_NONE;
+        }
+
+        if ((seclabel->type == VIR_DOMAIN_SECLABEL_NONE) &&
+            sec_managers[i]->requireConfined) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Unconfined guests are not allowed on this host"));
+            rc = -1;
+            goto cleanup;
+        }
+
+        if (!sec_managers[i]->drv->domainGenSecurityLabel) {
+            virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        } else {
+            rc += sec_managers[i]->drv->domainGenSecurityLabel(sec_managers[i], vm);
+            if (rc)
+                goto cleanup;
+        }
+    }
+
+cleanup:
+    VIR_FREE(sec_managers);
+    return rc;
 }
 
 int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr,
@@ -399,12 +430,17 @@ int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr,
 int virSecurityManagerVerify(virSecurityManagerPtr mgr,
                              virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    if (mgr == NULL || mgr->drv == NULL)
+        return 0;
+
     /* NULL model == dynamic labelling, with whatever driver
      * is active, so we can short circuit verify check to
      * avoid drivers de-referencing NULLs by accident
      */
-    if (!secdef->model)
+    secdef = virDomainDefGetSecurityLabelDef(def, mgr->drv->name);
+    if (secdef == NULL || secdef->model == NULL)
         return 0;
 
     if (mgr->drv->domainSecurityVerify)
@@ -437,3 +473,22 @@ char *virSecurityManagerGetMountOptions(virSecurityManagerPtr mgr,
     */
     return NULL;
 }
+
+virSecurityManagerPtr*
+virSecurityManagerGetNested(virSecurityManagerPtr mgr)
+{
+    virSecurityManagerPtr* list = NULL;
+
+    if (STREQ("stack", mgr->drv->name)) {
+        return virSecurityStackGetNested(mgr);
+    }
+
+    if (VIR_ALLOC_N(list, 2) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    list[0] = mgr;
+    list[1] = NULL;
+    return list;
+}
index 325fc1ea20abd90441e85626ed99c307e594af35..7d638068b32387aff88cf49ddacffb9456d1f6a9 100644 (file)
@@ -34,8 +34,9 @@ virSecurityManagerPtr virSecurityManagerNew(const char *name,
                                             bool defaultConfined,
                                             bool requireConfined);
 
-virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary,
-                                                 virSecurityManagerPtr secondary);
+virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary);
+int virSecurityManagerStackAddNested(virSecurityManagerPtr stack,
+                                     virSecurityManagerPtr nested);
 
 virSecurityManagerPtr virSecurityManagerNewDAC(const char *virtDriver,
                                                uid_t user,
@@ -106,4 +107,7 @@ int virSecurityManagerSetImageFDLabel(virSecurityManagerPtr mgr,
                                       int fd);
 char *virSecurityManagerGetMountOptions(virSecurityManagerPtr mgr,
                                               virDomainDefPtr vm);
+virSecurityManagerPtr*
+virSecurityManagerGetNested(virSecurityManagerPtr mgr);
+
 #endif /* VIR_SECURITY_MANAGER_H__ */
index 645232bb9e743b64c79f34c19af5430166d330cc..eea8fbdc6345cd43808f26700485793e2e4a9b33 100644 (file)
@@ -363,46 +363,52 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
     char *scontext = NULL;
     context_t ctx = NULL;
     const char *range;
-    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
+    virSecurityLabelDefPtr seclabel;
+    virSecuritySELinuxDataPtr data;
 
-    VIR_DEBUG("driver=%s", virSecurityManagerGetDriver(mgr));
-    if ((def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
-        !def->seclabels[0]->baselabel &&
-        def->seclabels[0]->model) {
+    if (mgr == NULL) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("security model already defined for VM"));
+                       "%s", _("invalid security driver"));
         return rc;
     }
 
-    if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
-        def->seclabels[0]->label) {
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (seclabel == NULL) {
+        return rc;
+    }
+
+    data = virSecurityManagerGetPrivateData(mgr);
+
+    VIR_DEBUG("label=%s", virSecurityManagerGetDriver(mgr));
+    if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+        seclabel->label) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("security label already defined for VM"));
         return rc;
     }
 
-    if (def->seclabels[0]->imagelabel) {
+    if (seclabel->imagelabel) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("security image label already defined for VM"));
         return rc;
     }
 
-    if (def->seclabels[0]->model &&
-        STRNEQ(def->seclabels[0]->model, SECURITY_SELINUX_NAME)) {
+    if (seclabel->model &&
+        STRNEQ(seclabel->model, SECURITY_SELINUX_NAME)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security label model %s is not supported with selinux"),
-                       def->seclabels[0]->model);
+                       seclabel->model);
         return rc;
     }
 
-    VIR_DEBUG("type%d", def->seclabels[0]->type);
+    VIR_DEBUG("type=%d", seclabel->type);
 
-    switch (def->seclabels[0]->type) {
+    switch (seclabel->type) {
     case VIR_DOMAIN_SECLABEL_STATIC:
-        if (!(ctx = context_new(def->seclabels[0]->label)) ) {
+        if (!(ctx = context_new(seclabel->label)) ) {
             virReportSystemError(errno,
                                  _("unable to allocate socket security context '%s'"),
-                                 def->seclabels[0]->label);
+                                 seclabel->label);
             return rc;
         }
 
@@ -421,11 +427,11 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
         if (virSecuritySELinuxMCSAdd(mgr, mcs) < 0)
             goto cleanup;
 
-        def->seclabels[0]->label =
-            virSecuritySELinuxGenNewContext(def->seclabels[0]->baselabel ?
-                                            def->seclabels[0]->baselabel :
-                                            data->domain_context, mcs, false);
-        if (! def->seclabels[0]->label)  {
+        seclabel->label =
+            virSecuritySELinuxGenNewContext(seclabel->baselabel ?
+                                 seclabel->baselabel :
+                                 data->domain_context, mcs, false);
+        if (!seclabel->label)  {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot generate selinux context for %s"), mcs);
             goto cleanup;
@@ -439,23 +445,23 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
     default:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected security label type '%s'"),
-                       virDomainSeclabelTypeToString(def->seclabels[0]->type));
+                       virDomainSeclabelTypeToString(seclabel->type));
         goto cleanup;
     }
 
-    if (!def->seclabels[0]->norelabel) {
-        def->seclabels[0]->imagelabel = virSecuritySELinuxGenNewContext(data->file_context,
-                                                                        mcs,
-                                                                        true);
-        if (!def->seclabels[0]->imagelabel)  {
+    if (!seclabel->norelabel) {
+        seclabel->imagelabel = virSecuritySELinuxGenNewContext(data->domain_context,
+                                                               mcs,
+                                                               true);
+        if (!seclabel->imagelabel)  {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot generate selinux context for %s"), mcs);
             goto cleanup;
         }
     }
 
-    if (!def->seclabels[0]->model &&
-        !(def->seclabels[0]->model = strdup(SECURITY_SELINUX_NAME))) {
+    if (!seclabel->model &&
+        !(seclabel->model = strdup(SECURITY_SELINUX_NAME))) {
         virReportOOMError();
         goto cleanup;
     }
@@ -464,12 +470,12 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
 
 cleanup:
     if (rc != 0) {
-        if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
-            VIR_FREE(def->seclabels[0]->label);
-        VIR_FREE(def->seclabels[0]->imagelabel);
-        if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
-            !def->seclabels[0]->baselabel)
-            VIR_FREE(def->seclabels[0]->model);
+        if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
+            VIR_FREE(seclabel->label);
+        VIR_FREE(seclabel->imagelabel);
+        if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+            !seclabel->baselabel)
+            VIR_FREE(seclabel->model);
     }
 
     if (ctx)
@@ -478,10 +484,10 @@ cleanup:
     VIR_FREE(mcs);
 
     VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
-              NULLSTR(def->seclabels[0]->model),
-              NULLSTR(def->seclabels[0]->label),
-              NULLSTR(def->seclabels[0]->imagelabel),
-              NULLSTR(def->seclabels[0]->baselabel));
+              NULLSTR(seclabel->model),
+              NULLSTR(seclabel->label),
+              NULLSTR(seclabel->imagelabel),
+              NULLSTR(seclabel->baselabel));
 
     return rc;
 }
@@ -495,8 +501,14 @@ virSecuritySELinuxReserveSecurityLabel(virSecurityManagerPtr mgr,
     context_t ctx = NULL;
     const char *mcs;
     int rv;
+    virSecurityLabelDefPtr seclabel;
 
-    if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_STATIC)
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (seclabel == NULL) {
+        return -1;
+    }
+
+    if (seclabel->type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
 
     if (getpidcon(pid, &pctx) == -1) {
@@ -800,9 +812,16 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBU
                                                virDomainDiskDefPtr disk,
                                                int migrated)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr seclabel;
+    virSecurityDeviceLabelDefPtr disk_seclabel;
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (seclabel == NULL)
+        return -1;
 
-    if (secdef->norelabel || (disk->seclabels[0] && disk->seclabels[0]->norelabel))
+    disk_seclabel = virDomainDiskDefGetSecurityLabelDef(disk,
+                                                        SECURITY_SELINUX_NAME);
+    if (seclabel->norelabel || (disk_seclabel && disk_seclabel->norelabel))
         return 0;
 
     /* Don't restore labels on readoly/shared disks, because
@@ -854,17 +873,21 @@ virSecuritySELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
                                        size_t depth,
                                        void *opaque)
 {
+    int ret;
+    virSecurityDeviceLabelDefPtr disk_seclabel;
     virSecuritySELinuxCallbackDataPtr cbdata = opaque;
     const virSecurityLabelDefPtr secdef = cbdata->secdef;
-    int ret;
     virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(cbdata->manager);
 
-    if (disk->seclabels[0] && disk->seclabels[0]->norelabel)
+    disk_seclabel = virDomainDiskDefGetSecurityLabelDef(disk,
+                                                        SECURITY_SELINUX_NAME);
+
+    if (disk_seclabel && disk_seclabel->norelabel)
         return 0;
 
-    if (disk->seclabels[0] && !disk->seclabels[0]->norelabel &&
-        disk->seclabels[0]->label) {
-        ret = virSecuritySELinuxSetFilecon(path, disk->seclabels[0]->label);
+    if (disk_seclabel && !disk_seclabel->norelabel &&
+        disk_seclabel->label) {
+        ret = virSecuritySELinuxSetFilecon(path, disk_seclabel->label);
     } else if (depth == 0) {
 
         if (disk->shared) {
@@ -879,14 +902,14 @@ virSecuritySELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
     } else {
         ret = virSecuritySELinuxSetFileconOptional(path, data->content_context);
     }
-    if (ret == 1 && !disk->seclabels[0]) {
+    if (ret == 1 && !disk_seclabel) {
         /* If we failed to set a label, but virt_use_nfs let us
          * proceed anyway, then we don't need to relabel later.  */
-        if (VIR_ALLOC(disk->seclabels[0]) < 0) {
+        if (VIR_ALLOC(disk_seclabel) < 0) {
             virReportOOMError();
             return -1;
         }
-        disk->seclabels[0]->norelabel = true;
+        disk_seclabel->norelabel = true;
         ret = 0;
     }
     return ret;
@@ -898,11 +921,15 @@ virSecuritySELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                         virDomainDiskDefPtr disk)
 
 {
+    bool allowDiskFormatProbing;
     virSecuritySELinuxCallbackData cbdata;
-    cbdata.secdef = def->seclabels[0];
     cbdata.manager = mgr;
+    cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
 
-    bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
+    allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
+
+    if (cbdata.secdef == NULL)
+        return -1;
 
     if (cbdata.secdef->norelabel)
         return 0;
@@ -929,9 +956,12 @@ static int
 virSecuritySELinuxSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
                                       const char *file, void *opaque)
 {
+    virSecurityLabelDefPtr secdef;
     virDomainDefPtr def = opaque;
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
     return virSecuritySELinuxSetFilecon(file, secdef->imagelabel);
 }
 
@@ -939,8 +969,12 @@ static int
 virSecuritySELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
                                       const char *file, void *opaque)
 {
+    virSecurityLabelDefPtr secdef;
     virDomainDefPtr def = opaque;
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     return virSecuritySELinuxSetFilecon(file, secdef->imagelabel);
 }
@@ -951,9 +985,13 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN
                                           virDomainHostdevDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     int ret = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -1020,9 +1058,13 @@ virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT
                                               virDomainHostdevDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     int ret = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -1073,10 +1115,14 @@ virSecuritySELinuxSetSecurityChardevLabel(virDomainDefPtr def,
                                           virDomainChrSourceDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     char *in = NULL, *out = NULL;
     int ret = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -1119,10 +1165,14 @@ virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def,
                                               virDomainChrSourceDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     char *in = NULL, *out = NULL;
     int ret = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -1212,12 +1262,16 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN
                                           virDomainDefPtr def,
                                           int migrated ATTRIBUTE_UNUSED)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     int i;
     int rc = 0;
 
     VIR_DEBUG("Restoring security label on %s", def->name);
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -1262,7 +1316,11 @@ static int
 virSecuritySELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr,
                                        virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
         if (secdef->label != NULL) {
@@ -1287,7 +1345,11 @@ virSecuritySELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                      virDomainDefPtr def,
                                      const char *savefile)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -1301,7 +1363,11 @@ virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNU
                                          virDomainDefPtr def,
                                          const char *savefile)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -1314,7 +1380,12 @@ static int
 virSecuritySELinuxSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                  virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security label driver mismatch: "
@@ -1339,12 +1410,16 @@ virSecuritySELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr,
                                           virDomainDefPtr def)
 {
     /* TODO: verify DOI */
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
-    VIR_DEBUG("label=%s", secdef->label);
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
-    if (def->seclabels[0]->label == NULL)
+    if (secdef->label == NULL)
         return 0;
 
+    VIR_DEBUG("label=%s", secdef->label);
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security label driver mismatch: "
@@ -1371,13 +1446,17 @@ virSecuritySELinuxSetSecurityDaemonSocketLabel(virSecurityManagerPtr mgr,
                                                virDomainDefPtr def)
 {
     /* TODO: verify DOI */
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     context_t execcon = NULL;
     context_t proccon = NULL;
     security_context_t scon = NULL;
     int rc = -1;
 
-    if (def->seclabels[0]->label == NULL)
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
+    if (secdef->label == NULL)
         return 0;
 
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
@@ -1441,9 +1520,13 @@ static int
 virSecuritySELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr,
                                          virDomainDefPtr vm)
 {
-    const virSecurityLabelDefPtr secdef = vm->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     int rc = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(vm, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->label == NULL)
         return 0;
 
@@ -1479,9 +1562,13 @@ virSecuritySELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr,
                                            virDomainDefPtr def)
 {
     /* TODO: verify DOI */
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
-    if (def->seclabels[0]->label == NULL)
+    if (secdef->label == NULL)
         return 0;
 
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
@@ -1557,9 +1644,13 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
                                       virDomainDefPtr def,
                                       const char *stdin_path)
 {
-    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
     int i;
+    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -1619,7 +1710,11 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                   virDomainDefPtr def,
                                   int fd)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->imagelabel == NULL)
         return 0;
@@ -1631,13 +1726,17 @@ static char *
 virSecuritySELinuxGenImageLabel(virSecurityManagerPtr mgr,
                                 virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
     virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
     const char *range;
     context_t ctx = NULL;
     char *label = NULL;
     const char *mcs = NULL;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        goto cleanup;
+
     if (secdef->label) {
         ctx = context_new(secdef->label);
         if (!ctx) {
@@ -1668,7 +1767,11 @@ virSecuritySELinuxGetSecurityMountOptions(virSecurityManagerPtr mgr,
                                           virDomainDefPtr def)
 {
     char *opts = NULL;
-    const virSecurityLabelDefPtr secdef = def->seclabels[0];
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return NULL;
 
     if (! secdef->imagelabel)
         secdef->imagelabel = virSecuritySELinuxGenImageLabel(mgr,def);
index 65d9dd749d44ad999eb138d223a0cb64c00e92cb..7dcd626293ba42066e51f4aee122e9ef8cf71c2f 100644 (file)
 #include "security_stack.h"
 
 #include "virterror_internal.h"
+#include "memory.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
 
 typedef struct _virSecurityStackData virSecurityStackData;
 typedef virSecurityStackData *virSecurityStackDataPtr;
+typedef struct _virSecurityStackItem virSecurityStackItem;
+typedef virSecurityStackItem* virSecurityStackItemPtr;
+
+struct _virSecurityStackItem {
+    virSecurityManagerPtr securityManager;
+    virSecurityStackItemPtr next;
+};
 
 struct _virSecurityStackData {
     virSecurityManagerPtr primary;
-    virSecurityManagerPtr secondary;
+    virSecurityStackItemPtr itemsHead;
 };
 
-void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
-                                virSecurityManagerPtr primary)
+int
+virSecurityStackAddPrimary(virSecurityManagerPtr mgr,
+                           virSecurityManagerPtr primary)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    if (virSecurityStackAddNested(mgr, primary) < 0)
+        return -1;
     priv->primary = primary;
+    return 0;
+}
+
+int
+virSecurityStackAddNested(virSecurityManagerPtr mgr,
+                          virSecurityManagerPtr nested)
+{
+    virSecurityStackItemPtr item = NULL;
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    if (VIR_ALLOC(item) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+    item->securityManager = nested;
+    item->next = priv->itemsHead;
+    priv->itemsHead = item;
+    return 0;
+}
+
+virSecurityManagerPtr
+virSecurityStackGetPrimary(virSecurityManagerPtr mgr)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    return (priv->primary) ? priv->primary : priv->itemsHead->securityManager;
+}
+
+void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
+                                virSecurityManagerPtr primary)
+{
+    virSecurityStackAddPrimary(mgr, primary);
 }
 
 void virSecurityStackSetSecondary(virSecurityManagerPtr mgr,
                                   virSecurityManagerPtr secondary)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
-    priv->secondary = secondary;
+    virSecurityStackAddNested(mgr, secondary);
 }
 
 static virSecurityDriverStatus
@@ -64,9 +105,14 @@ static int
 virSecurityStackClose(virSecurityManagerPtr mgr)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr next, item = priv->itemsHead;
 
-    virSecurityManagerFree(priv->primary);
-    virSecurityManagerFree(priv->secondary);
+    while (item) {
+        next = item->next;
+        virSecurityManagerFree(item->securityManager);
+        VIR_FREE(item);
+        item = next;
+    }
 
     return 0;
 }
@@ -74,17 +120,13 @@ virSecurityStackClose(virSecurityManagerPtr mgr)
 static const char *
 virSecurityStackGetModel(virSecurityManagerPtr mgr)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
-
-    return virSecurityManagerGetModel(priv->primary);
+    return virSecurityManagerGetModel(virSecurityStackGetPrimary(mgr));
 }
 
 static const char *
 virSecurityStackGetDOI(virSecurityManagerPtr mgr)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
-
-    return virSecurityManagerGetDOI(priv->primary);
+    return virSecurityManagerGetDOI(virSecurityStackGetPrimary(mgr));
 }
 
 static int
@@ -92,13 +134,15 @@ virSecurityStackVerify(virSecurityManagerPtr mgr,
                        virDomainDefPtr def)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerVerify(priv->primary, def) < 0)
-        rc = -1;
-
-    if (virSecurityManagerVerify(priv->secondary, def) < 0)
-        rc = -1;
+    for(; item; item = item->next) {
+        if (virSecurityManagerVerify(item->securityManager, def) < 0) {
+            rc = -1;
+            break;
+        }
+    }
 
     return rc;
 }
@@ -108,12 +152,12 @@ static int
 virSecurityStackGenLabel(virSecurityManagerPtr mgr,
                          virDomainDefPtr vm)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int rc = 0;
 
-    if (virSecurityManagerGenLabel(priv->primary, vm) < 0)
+    if (virSecurityManagerGenLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
         rc = -1;
 
+// TODO
 #if 0
     /* We don't allow secondary drivers to generate labels.
      * This may have to change in the future, but requires
@@ -133,11 +177,12 @@ static int
 virSecurityStackReleaseLabel(virSecurityManagerPtr mgr,
                              virDomainDefPtr vm)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int rc = 0;
 
-    if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0)
+    if (virSecurityManagerReleaseLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
         rc = -1;
+
+// TODO
 #if 0
     /* XXX See note in GenLabel */
     if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
@@ -153,11 +198,11 @@ virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
                              virDomainDefPtr vm,
                              pid_t pid)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int rc = 0;
 
-    if (virSecurityManagerReserveLabel(priv->primary, vm, pid) < 0)
+    if (virSecurityManagerReserveLabel(virSecurityStackGetPrimary(mgr), vm, pid) < 0)
         rc = -1;
+// TODO
 #if 0
     /* XXX See note in GenLabel */
     if (virSecurityManagerReserveLabel(priv->secondary, vm, pid) < 0)
@@ -174,12 +219,13 @@ virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                       virDomainDiskDefPtr disk)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetImageLabel(priv->secondary, vm, disk) < 0)
-        rc = -1;
-    if (virSecurityManagerSetImageLabel(priv->primary, vm, disk) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetImageLabel(item->securityManager, vm, disk) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -191,12 +237,13 @@ virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
                                           virDomainDiskDefPtr disk)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerRestoreImageLabel(priv->secondary, vm, disk) < 0)
-        rc = -1;
-    if (virSecurityManagerRestoreImageLabel(priv->primary, vm, disk) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerRestoreImageLabel(item->securityManager, vm, disk) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -209,12 +256,13 @@ virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
 
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetHostdevLabel(priv->secondary, vm, dev) < 0)
-        rc = -1;
-    if (virSecurityManagerSetHostdevLabel(priv->primary, vm, dev) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetHostdevLabel(item->securityManager, vm, dev) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -226,12 +274,13 @@ virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
                                             virDomainHostdevDefPtr dev)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerRestoreHostdevLabel(priv->secondary, vm, dev) < 0)
-        rc = -1;
-    if (virSecurityManagerRestoreHostdevLabel(priv->primary, vm, dev) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerRestoreHostdevLabel(item->securityManager, vm, dev) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -243,12 +292,13 @@ virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
                                     const char *stdin_path)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetAllLabel(priv->secondary, vm, stdin_path) < 0)
-        rc = -1;
-    if (virSecurityManagerSetAllLabel(priv->primary, vm, stdin_path) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetAllLabel(item->securityManager, vm, stdin_path) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -260,12 +310,13 @@ virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
                                         int migrated)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerRestoreAllLabel(priv->secondary, vm, migrated) < 0)
-        rc = -1;
-    if (virSecurityManagerRestoreAllLabel(priv->primary, vm, migrated) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerRestoreAllLabel(item->securityManager, vm, migrated) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -277,12 +328,13 @@ virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
                                    const char *savefile)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetSavedStateLabel(priv->secondary, vm, savefile) < 0)
-        rc = -1;
-    if (virSecurityManagerSetSavedStateLabel(priv->primary, vm, savefile) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetSavedStateLabel(item->securityManager, vm, savefile) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -294,12 +346,13 @@ virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
                                        const char *savefile)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerRestoreSavedStateLabel(priv->secondary, vm, savefile) < 0)
-        rc = -1;
-    if (virSecurityManagerRestoreSavedStateLabel(priv->primary, vm, savefile) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerRestoreSavedStateLabel(item->securityManager, vm, savefile) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -310,12 +363,13 @@ virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
                                 virDomainDefPtr vm)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetProcessLabel(priv->secondary, vm) < 0)
-        rc = -1;
-    if (virSecurityManagerSetProcessLabel(priv->primary, vm) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetProcessLabel(item->securityManager, vm) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -326,14 +380,14 @@ virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
                                 pid_t pid,
                                 virSecurityLabelPtr seclabel)
 {
-    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int rc = 0;
 
+// TODO
 #if 0
     if (virSecurityManagerGetProcessLabel(priv->secondary, vm, pid, seclabel) < 0)
         rc = -1;
 #endif
-    if (virSecurityManagerGetProcessLabel(priv->primary, vm, pid, seclabel) < 0)
+    if (virSecurityManagerGetProcessLabel(virSecurityStackGetPrimary(mgr), vm, pid, seclabel) < 0)
         rc = -1;
 
     return rc;
@@ -345,12 +399,13 @@ virSecurityStackSetDaemonSocketLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr vm)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetDaemonSocketLabel(priv->secondary, vm) < 0)
-        rc = -1;
-    if (virSecurityManagerSetDaemonSocketLabel(priv->primary, vm) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetDaemonSocketLabel(item->securityManager, vm) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -361,12 +416,13 @@ virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
                                virDomainDefPtr vm)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetSocketLabel(priv->secondary, vm) < 0)
-        rc = -1;
-    if (virSecurityManagerSetSocketLabel(priv->primary, vm) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetSocketLabel(item->securityManager, vm) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -377,12 +433,13 @@ virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
                                  virDomainDefPtr vm)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerClearSocketLabel(priv->secondary, vm) < 0)
-        rc = -1;
-    if (virSecurityManagerClearSocketLabel(priv->primary, vm) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerClearSocketLabel(item->securityManager, vm) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -393,12 +450,13 @@ virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
                                 int fd)
 {
     virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item = priv->itemsHead;
     int rc = 0;
 
-    if (virSecurityManagerSetImageFDLabel(priv->secondary, vm, fd) < 0)
-        rc = -1;
-    if (virSecurityManagerSetImageFDLabel(priv->primary, vm, fd) < 0)
-        rc = -1;
+    for (; item; item = item->next) {
+        if (virSecurityManagerSetImageFDLabel(item->securityManager, vm, fd) < 0)
+            rc = -1;
+    }
 
     return rc;
 }
@@ -408,6 +466,29 @@ static char *virSecurityStackGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE
     return NULL;
 }
 
+virSecurityManagerPtr*
+virSecurityStackGetNested(virSecurityManagerPtr mgr)
+{
+    virSecurityManagerPtr *list = NULL;
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    virSecurityStackItemPtr item;
+    int len = 0, i = 0;
+
+    for (item = priv->itemsHead; item; item = item->next)
+        len++;
+
+    if (VIR_ALLOC_N(list, len + 1) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    for (item = priv->itemsHead; item; item = item->next, i++)
+        list[i] = item->securityManager;
+    list[len] = NULL;
+
+    return list;
+}
+
 virSecurityDriver virSecurityDriverStack = {
     .privateDataLen                     = sizeof(virSecurityStackData),
     .name                               = "stack",
index fd0d26f197746aae6ac2a0d361c6cc2c6cb2caa4..6898c03b7f0922e53ff355d5e0f125d8d9ea84ea 100644 (file)
 
 extern virSecurityDriver virSecurityDriverStack;
 
+
+int
+virSecurityStackAddPrimary(virSecurityManagerPtr mgr,
+                           virSecurityManagerPtr primary);
+int
+virSecurityStackAddNested(virSecurityManagerPtr mgr,
+                          virSecurityManagerPtr nested);
+virSecurityManagerPtr
+virSecurityStackGetPrimary(virSecurityManagerPtr mgr);
+
 void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
                                 virSecurityManagerPtr primary);
 void virSecurityStackSetSecondary(virSecurityManagerPtr mgr,
                                   virSecurityManagerPtr secondary);
 
+virSecurityManagerPtr*
+virSecurityStackGetNested(virSecurityManagerPtr mgr);
+
 #endif /* __VIR_SECURITY_DAC */