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

Michal Privoznik mprivozn at redhat.com
Tue Jun 5 14:38:51 UTC 2012


On 21.05.2012 15:39, Marcelo Cerri wrote:
> ---
>  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(-)
> 

Doesn't apply cleanly:

CONFLICT (content): Merge conflict in src/security/security_dac.c

However, this is caused by my earlier patch which converted security
driver struct initialization to follow C99 hence conflict can be
resolved easily.

> 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;
> +}
> +

Again, blank newline on the EOF.

> 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 */




More information about the libvir-list mailing list