[libvirt] [PATCH 2/7] Update security drivers to handle multiple security labels in internal data structures

Marcelo Cerri mhcerri at linux.vnet.ibm.com
Mon May 21 13:39:24 UTC 2012


---
 src/security/security_apparmor.c |  112 ++++++++++----
 src/security/security_dac.c      |  320 ++++++++++++++++++++++++++++++++++----
 src/security/security_manager.c  |   99 +++++++++---
 src/security/security_manager.h  |    8 +-
 src/security/security_selinux.c  |  249 +++++++++++++++++++++---------
 src/security/security_stack.c    |  235 +++++++++++++++++++---------
 src/security/security_stack.h    |   13 ++
 7 files changed, 803 insertions(+), 233 deletions(-)

diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index 2d05fd0..d5d41f6 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -262,9 +262,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;
@@ -298,7 +302,12 @@ 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;
+        }
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot update AppArmor profile "
                                  "\'%s\'"),
@@ -316,7 +325,12 @@ 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;
+        }
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot update AppArmor profile "
                                  "\'%s\'"),
@@ -398,18 +412,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) {
         virSecurityReportError(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)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s",
                                _("security label already defined for VM"));
@@ -419,31 +438,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) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot load AppArmor profile "
-                               "\'%s\'"), def->seclabel.label);
+                               "\'%s\'"), secdef->label);
         goto err;
     }
 
@@ -451,9 +470,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);
@@ -465,7 +484,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
@@ -518,7 +542,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);
@@ -533,8 +560,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) {
@@ -552,9 +583,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;
@@ -621,9 +656,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;
@@ -666,7 +705,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) {
@@ -694,9 +737,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;
@@ -756,7 +803,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;
 
@@ -789,7 +841,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;
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 470861d..0badafb 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -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,132 @@ 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;
+
+    uid = strtol(label, &endptr, 10);
+    if (endptr == NULL || *endptr != ':')
+        return -1;
+
+    gid = strtol(endptr + 1, &endptr, 10);
+    if (endptr == NULL || *endptr != '\0')
+        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) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("security label for DAC not found"));
+        return -1;
+    }
+
+    if (seclabel->label && parseIds(seclabel->label, &uid, &gid)) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("failed to parse uid and gid for DAC "
+                                 "securit driver"));
+        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) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("security label for DAC not found"));
+        return -1;
+    }
+
+    if (seclabel->imagelabel
+        && parseIds(seclabel->imagelabel, &uid, &gid)) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("failed to parse uid and gid for DAC "
+                                 "securit driver"));
+        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 +212,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 +294,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;
 
-    return virSecurityDACSetOwnership(path, priv->user, priv->group);
+    if (virSecurityDACGetImageIds(def, priv, &user, &group))
+        return -1;
+
+    return virSecurityDACSetOwnership(path, user, group);
 }
 
 
@@ -180,6 +314,9 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                     virDomainDiskDefPtr disk)
 
 {
+    uid_t user;
+    gid_t group;
+    void *params[2];
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
 
     if (!priv->dynamicOwnership)
@@ -188,12 +325,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 +401,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;
+
+    if (virSecurityDACGetIds(def, priv, &user, &group))
+        return -1;
 
-    return virSecurityDACSetOwnership(file, priv->user, priv->group);
+    return virSecurityDACSetOwnership(file, user, group);
 }
 
 
@@ -271,18 +420,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 +457,8 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
         if (!usb)
             goto done;
 
-        ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr);
+        ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel,
+                                   params);
         usbFreeDevice(usb);
         break;
     }
@@ -314,7 +472,8 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
         if (!pci)
             goto done;
 
-        ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr);
+        ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel,
+                                   params);
         pciFreeDevice(pci);
 
         break;
@@ -404,17 +563,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 +589,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 +719,7 @@ virSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
 {
     virSecurityManagerPtr mgr = opaque;
 
-    return virSecurityDACSetChardevLabel(mgr, &dev->source);
+    return virSecurityDACSetChardevLabel(mgr, def, &dev->source);
 }
 
 
@@ -565,6 +730,8 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
 {
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
     int i;
+    uid_t user;
+    gid_t group;
 
     if (!priv->dynamicOwnership)
         return 0;
@@ -591,16 +758,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 +775,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 +807,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 +831,83 @@ 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) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("invalid security driver"));
+        return rc;
+    }
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
+    if (seclabel == NULL) {
+        return rc;
+    }
+
+    if (seclabel->imagelabel) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("security image label already "
+                                 "defined for VM"));
+        return rc;
+    }
+
+    if (seclabel->model
+        && STRNEQ(seclabel->model, SECURITY_DAC_NAME)) {
+        virSecurityReportError(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) {
+            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("missing label for static security "
+                                     "driver"));
+            return rc;
+        }
+        break;
+    case VIR_DOMAIN_SECLABEL_DYNAMIC:
+        if (asprintf(&seclabel->label, "%d:%d", priv->user, priv->group) < 0) {
+            virReportOOMError();
+            return rc;
+        }
+        if (seclabel->label == NULL) {
+            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("cannot generate dac user and group id"));
+            return rc;
+        }
+        break;
+    case VIR_DOMAIN_SECLABEL_NONE:
+        /* no op */
+        break;
+    default:
+        virSecurityReportError(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) {
+                virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("cannot generate dac user and group id"));
+                VIR_FREE(seclabel->label);
+                seclabel->label = NULL;
+                return rc;
+            }
+        }
+    }
+
     return 0;
 }
 
@@ -683,6 +932,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 +982,7 @@ static char *virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_U
 
 virSecurityDriver virSecurityDriverDAC = {
     sizeof(virSecurityDACData),
-    "virDAC",
+    SECURITY_DAC_NAME,
 
     virSecurityDACProbe,
     virSecurityDACOpen,
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index 8ec4d3e..a9ca824 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -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,25 +314,51 @@ int virSecurityManagerRestoreSavedStateLabel(virSecurityManagerPtr mgr,
 int virSecurityManagerGenLabel(virSecurityManagerPtr mgr,
                                virDomainDefPtr vm)
 {
-    if (vm->seclabel.type == VIR_DOMAIN_SECLABEL_DEFAULT) {
-        if (mgr->defaultConfined)
-            vm->seclabel.type = VIR_DOMAIN_SECLABEL_DYNAMIC;
-        else
-            vm->seclabel.type = VIR_DOMAIN_SECLABEL_NONE;
-    }
+    int rc = 0;
+    size_t i;
+    virSecurityManagerPtr* sec_managers = NULL;
+    virSecurityLabelDefPtr seclabel;
 
-    if ((vm->seclabel.type == VIR_DOMAIN_SECLABEL_NONE) &&
-        mgr->requireConfined) {
-        virSecurityReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("Unconfined guests are not allowed on this host"));
+    if (mgr == NULL || mgr->drv == NULL)
         return -1;
-    }
 
-    if (mgr->drv->domainGenSecurityLabel)
-        return mgr->drv->domainGenSecurityLabel(mgr, vm);
+    if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL)
+        return -1;
 
-    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
+    for (i = 0; sec_managers[i]; i++) {
+        seclabel = virDomainDefGetSecurityLabelDef(vm,
+                                                   sec_managers[i]->drv->name);
+        if (seclabel == NULL) {
+            rc = -1;
+            goto cleanup;
+        }
+
+        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) {
+            virSecurityReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                   _("Unconfined guests are not allowed on this host"));
+            return -1;
+        }
+
+        if (!sec_managers[i]->drv->domainGenSecurityLabel) {
+            virSecurityReportError(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,
@@ -397,12 +429,17 @@ int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr,
 int virSecurityManagerVerify(virSecurityManagerPtr mgr,
                              virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    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)
@@ -435,3 +472,23 @@ 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;
+}
+
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index f0bf60d..f86b84d 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -37,8 +37,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,
@@ -109,4 +110,7 @@ int virSecurityManagerSetImageFDLabel(virSecurityManagerPtr mgr,
                                       int fd);
 char *virSecurityManagerGetMountOptions(virSecurityManagerPtr mgr,
                                               virDomainDefPtr vm);
+virSecurityManagerPtr*
+virSecurityManagerGetNested(virSecurityManagerPtr mgr);
+
 #endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 2b8ff19..fe318be 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -271,46 +271,52 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
     int c2 = 0;
     context_t ctx = NULL;
     const char *range;
-    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
+    virSecurityLabelDefPtr seclabel;
+    virSecuritySELinuxDataPtr data;
 
-    VIR_DEBUG("SELinuxGenSecurityLabel %s", virSecurityManagerGetDriver(mgr));
-    if ((def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
-        !def->seclabel.baselabel &&
-        def->seclabel.model) {
+    if (mgr == NULL) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
-                               "%s", _("security model already defined for VM"));
+                               "%s", _("invalid security driver"));
+        return rc;
+    }
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (seclabel == NULL) {
         return rc;
     }
 
-    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
-        def->seclabel.label) {
+    data = virSecurityManagerGetPrivateData(mgr);
+
+    VIR_DEBUG("SELinuxGenSecurityLabel %s", virSecurityManagerGetDriver(mgr));
+    if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+        seclabel->label) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("security label already defined for VM"));
         return rc;
     }
 
-    if (def->seclabel.imagelabel) {
+    if (seclabel->imagelabel) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("security image label already defined for VM"));
         return rc;
     }
 
-    if (def->seclabel.model &&
-        STRNEQ(def->seclabel.model, SECURITY_SELINUX_NAME)) {
+    if (seclabel->model &&
+        STRNEQ(seclabel->model, SECURITY_SELINUX_NAME)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label model %s is not supported with selinux"),
-                               def->seclabel.model);
+                               seclabel->model);
         return rc;
     }
 
-    VIR_DEBUG("SELinuxGenSecurityLabel %d", def->seclabel.type);
+    VIR_DEBUG("SELinuxGenSecurityLabel %d", seclabel->type);
 
-    switch (def->seclabel.type) {
+    switch (seclabel->type) {
     case VIR_DOMAIN_SECLABEL_STATIC:
-        if (!(ctx = context_new(def->seclabel.label)) ) {
+        if (!(ctx = context_new(seclabel->label)) ) {
             virReportSystemError(errno,
                                  _("unable to allocate socket security context '%s'"),
-                                 def->seclabel.label);
+                                 seclabel->label);
             return rc;
         }
 
@@ -345,11 +351,11 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
             }
         } while (mcsAdd(mcs) == -1);
 
-        def->seclabel.label =
-            SELinuxGenNewContext(def->seclabel.baselabel ?
-                                 def->seclabel.baselabel :
+        seclabel->label =
+            SELinuxGenNewContext(seclabel->baselabel ?
+                                 seclabel->baselabel :
                                  data->domain_context, mcs);
-        if (! def->seclabel.label)  {
+        if (! seclabel->label)  {
             virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("cannot generate selinux context for %s"), mcs);
             goto cleanup;
@@ -363,21 +369,21 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
     default:
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unexpected security label type '%s'"),
-                               virDomainSeclabelTypeToString(def->seclabel.type));
+                               virDomainSeclabelTypeToString(seclabel->type));
         goto cleanup;
     }
 
-    if (!def->seclabel.norelabel) {
-        def->seclabel.imagelabel = SELinuxGenNewContext(data->file_context, mcs);
-        if (!def->seclabel.imagelabel)  {
+    if (!seclabel->norelabel) {
+        seclabel->imagelabel = SELinuxGenNewContext(data->domain_context, mcs);
+        if (!seclabel->imagelabel)  {
             virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("cannot generate selinux context for %s"), mcs);
             goto cleanup;
         }
     }
 
-    if (!def->seclabel.model &&
-        !(def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) {
+    if (!seclabel->model &&
+        !(seclabel->model = strdup(SECURITY_SELINUX_NAME))) {
         virReportOOMError();
         goto cleanup;
     }
@@ -386,12 +392,12 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
 
 cleanup:
     if (rc != 0) {
-        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
-            VIR_FREE(def->seclabel.label);
-        VIR_FREE(def->seclabel.imagelabel);
-        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
-            !def->seclabel.baselabel)
-            VIR_FREE(def->seclabel.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)
@@ -400,10 +406,10 @@ cleanup:
     VIR_FREE(mcs);
 
     VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
-              NULLSTR(def->seclabel.model),
-              NULLSTR(def->seclabel.label),
-              NULLSTR(def->seclabel.imagelabel),
-              NULLSTR(def->seclabel.baselabel));
+              NULLSTR(seclabel->model),
+              NULLSTR(seclabel->label),
+              NULLSTR(seclabel->imagelabel),
+              NULLSTR(seclabel->baselabel));
 
     return rc;
 }
@@ -416,8 +422,14 @@ SELinuxReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
     security_context_t pctx;
     context_t ctx = NULL;
     const char *mcs;
+    virSecurityLabelDefPtr seclabel;
+
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (seclabel == NULL) {
+        return -1;
+    }
 
-    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
+    if (seclabel->type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
 
     if (getpidcon(pid, &pctx) == -1) {
@@ -709,9 +721,16 @@ SELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                     virDomainDiskDefPtr disk,
                                     int migrated)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr seclabel;
+    virSecurityDeviceLabelDefPtr disk_seclabel;
 
-    if (secdef->norelabel || (disk->seclabel && disk->seclabel->norelabel))
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (seclabel == NULL)
+        return -1;
+
+    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
@@ -763,17 +782,21 @@ SELinuxSetSecurityFileLabel(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->seclabel && disk->seclabel->norelabel)
+    disk_seclabel = virDomainDiskDefGetSecurityLabelDef(disk,
+                                                        SECURITY_SELINUX_NAME);
+
+    if (disk_seclabel && disk_seclabel->norelabel)
         return 0;
 
-    if (disk->seclabel && !disk->seclabel->norelabel &&
-        disk->seclabel->label) {
-        ret = SELinuxSetFilecon(path, disk->seclabel->label);
+    if (disk_seclabel && !disk_seclabel->norelabel &&
+        disk_seclabel->label) {
+        ret = SELinuxSetFilecon(path, disk_seclabel->label);
     } else if (depth == 0) {
 
         if (disk->shared) {
@@ -788,14 +811,14 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
     } else {
         ret = SELinuxSetFileconOptional(path, data->content_context);
     }
-    if (ret == 1 && !disk->seclabel) {
+    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->seclabel) < 0) {
+        if (VIR_ALLOC(disk_seclabel) < 0) {
             virReportOOMError();
             return -1;
         }
-        disk->seclabel->norelabel = true;
+        disk_seclabel->norelabel = true;
         ret = 0;
     }
     return ret;
@@ -807,11 +830,15 @@ SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
                              virDomainDiskDefPtr disk)
 
 {
+    bool allowDiskFormatProbing;
     virSecuritySELinuxCallbackData cbdata;
-    cbdata.secdef = &def->seclabel;
     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;
@@ -838,9 +865,12 @@ static int
 SELinuxSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
                            const char *file, void *opaque)
 {
+    virSecurityLabelDefPtr secdef;
     virDomainDefPtr def = opaque;
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
     return SELinuxSetFilecon(file, secdef->imagelabel);
 }
 
@@ -848,8 +878,12 @@ static int
 SELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
                            const char *file, void *opaque)
 {
+    virSecurityLabelDefPtr secdef;
     virDomainDefPtr def = opaque;
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     return SELinuxSetFilecon(file, secdef->imagelabel);
 }
@@ -860,9 +894,13 @@ SELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                virDomainHostdevDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
     int ret = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -929,9 +967,13 @@ SELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                    virDomainHostdevDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
     int ret = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->norelabel)
         return 0;
 
@@ -982,10 +1024,14 @@ SELinuxSetSecurityChardevLabel(virDomainDefPtr def,
                                virDomainChrSourceDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    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;
 
@@ -1028,10 +1074,14 @@ SELinuxRestoreSecurityChardevLabel(virDomainDefPtr def,
                                    virDomainChrSourceDefPtr dev)
 
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    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;
 
@@ -1121,12 +1171,16 @@ SELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                virDomainDefPtr def,
                                int migrated ATTRIBUTE_UNUSED)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    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;
 
@@ -1171,7 +1225,11 @@ static int
 SELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                             virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
         if (secdef->label != NULL) {
@@ -1196,7 +1254,11 @@ SELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                           virDomainDefPtr def,
                           const char *savefile)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -1210,7 +1272,11 @@ SELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                               virDomainDefPtr def,
                               const char *savefile)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -1223,7 +1289,12 @@ static int
 SELinuxSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                       virDomainDefPtr def)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label driver mismatch: "
@@ -1248,12 +1319,16 @@ SELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr,
                                virDomainDefPtr def)
 {
     /* TODO: verify DOI */
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
-    VIR_DEBUG("SELinuxSetSecurityProcessLabel %s", secdef->label);
+    virSecurityLabelDefPtr secdef;
 
-    if (def->seclabel.label == NULL)
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
+    if (secdef->label == NULL)
         return 0;
 
+    VIR_DEBUG("SELinuxSetSecurityProcessLabel %s", secdef->label);
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label driver mismatch: "
@@ -1280,13 +1355,17 @@ SELinuxSetSecurityDaemonSocketLabel(virSecurityManagerPtr mgr,
                                     virDomainDefPtr def)
 {
     /* TODO: verify DOI */
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
     context_t execcon = NULL;
     context_t proccon = NULL;
     security_context_t scon = NULL;
     int rc = -1;
 
-    if (def->seclabel.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)) {
@@ -1350,9 +1429,13 @@ static int
 SELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr,
                               virDomainDefPtr vm)
 {
-    const virSecurityLabelDefPtr secdef = &vm->seclabel;
+    virSecurityLabelDefPtr secdef;
     int rc = -1;
 
+    secdef = virDomainDefGetSecurityLabelDef(vm, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+
     if (secdef->label == NULL)
         return 0;
 
@@ -1388,9 +1471,13 @@ SELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr,
                                 virDomainDefPtr def)
 {
     /* TODO: verify DOI */
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
-    if (def->seclabel.label == NULL)
+    if (secdef->label == NULL)
         return 0;
 
     if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
@@ -1466,9 +1553,13 @@ SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
                            virDomainDefPtr def,
                            const char *stdin_path)
 {
-    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
     int i;
+    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->norelabel)
         return 0;
@@ -1528,7 +1619,11 @@ SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                        virDomainDefPtr def,
                        int fd)
 {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
 
     if (secdef->imagelabel == NULL)
         return 0;
@@ -1538,13 +1633,17 @@ SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
 
 static char *genImageLabel(virSecurityManagerPtr mgr,
                            virDomainDefPtr def) {
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    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) {
@@ -1575,7 +1674,11 @@ cleanup:
 static char *SELinuxGetSecurityMountOptions(virSecurityManagerPtr mgr,
                                             virDomainDefPtr def) {
     char *opts = NULL;
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
+    virSecurityLabelDefPtr secdef;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return NULL;
 
     if (! secdef->imagelabel)
         secdef->imagelabel = genImageLabel(mgr,def);
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
index 6ecd099..dd0aebc 100644
--- a/src/security/security_stack.c
+++ b/src/security/security_stack.c
@@ -23,29 +23,70 @@
 #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,13 @@ 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;
+    }
 
     return rc;
 }
@@ -108,12 +150,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 +175,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 +196,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 +217,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 +235,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 +254,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 +272,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 +290,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 +308,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 +326,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 +344,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 +361,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 +378,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 +397,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 +414,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 +431,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 +448,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 +464,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 = {
     sizeof(virSecurityStackData),
     "stack",
diff --git a/src/security/security_stack.h b/src/security/security_stack.h
index bc83ff3..13a7a88 100644
--- a/src/security/security_stack.h
+++ b/src/security/security_stack.h
@@ -25,9 +25,22 @@
 
 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 */
-- 
1.7.1




More information about the libvir-list mailing list