[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH v2 3/5] Update security layer to handle many security labels



On 18.07.2012 03:28, Marcelo Cerri wrote:
> These changes make the security drivers able to find and handle the
> correct security label information when more than one label is
> available. They also update the DAC driver to be used as an usual
> security driver.
> 
>  Please enter the commit message for your changes. Lines starting
> ---
>  src/libvirt_private.syms         |    3 +
>  src/qemu/qemu_driver.c           |   45 ++++--
>  src/qemu/qemu_process.c          |   53 +++++--
>  src/security/security_apparmor.c |  112 ++++++++++----
>  src/security/security_dac.c      |  320 ++++++++++++++++++++++++++++++++++----
>  src/security/security_manager.c  |   98 +++++++++---
>  src/security/security_manager.h  |    8 +-
>  src/security/security_selinux.c  |  249 +++++++++++++++++++++---------
>  src/security/security_stack.c    |  237 +++++++++++++++++++---------
>  src/security/security_stack.h    |   13 ++
>  10 files changed, 872 insertions(+), 266 deletions(-)
> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 03f7f3e..758f219 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -281,6 +281,7 @@ virDomainDefClearPCIAddresses;
>  virDomainDefFormat;
>  virDomainDefFormatInternal;
>  virDomainDefFree;
> +virDomainDefGetSecurityLabelDef;
>  virDomainDefParseFile;
>  virDomainDefParseNode;
>  virDomainDefParseString;
> @@ -968,6 +969,7 @@ virSecurityManagerClearSocketLabel;
>  virSecurityManagerFree;
>  virSecurityManagerGenLabel;
>  virSecurityManagerGetDOI;
> +virSecurityManagerGetNested;
>  virSecurityManagerGetModel;
>  virSecurityManagerGetProcessLabel;
>  virSecurityManagerNew;
> @@ -987,6 +989,7 @@ virSecurityManagerSetHostdevLabel;
>  virSecurityManagerSetProcessLabel;
>  virSecurityManagerSetSavedStateLabel;
>  virSecurityManagerSetSocketLabel;
> +virSecurityManagerStackAddNested;
>  virSecurityManagerVerify;
>  virSecurityManagerGetMountOptions;
>  
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index a512a45..1b02f28 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -240,8 +240,8 @@ qemuSecurityInit(struct qemud_driver *driver)
>          if (!dac)
>              goto error;
>  
> -        if (!(driver->securityManager = virSecurityManagerNewStack(mgr,
> -                                                                   dac))) {
> +        if (!(driver->securityManager = virSecurityManagerNewStack(mgr)) ||
> +            !(virSecurityManagerStackAddNested(mgr, dac))) {
>  
>              virSecurityManagerFree(dac);
>              goto error;
> @@ -263,7 +263,11 @@ static virCapsPtr
>  qemuCreateCapabilities(virCapsPtr oldcaps,
>                         struct qemud_driver *driver)
>  {
> +    size_t i;
>      virCapsPtr caps;
> +    virSecurityManagerPtr *sec_managers = NULL;
> +    /* Security driver data */
> +    const char *doi, *model;
>  
>      /* Basic host arch / guest machine capabilities */
>      if (!(caps = qemuCapsInit(oldcaps))) {
> @@ -288,31 +292,38 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
>          goto err_exit;
>      }
>  
> -    /* Security driver data */
> -    const char *doi, *model;
> +    /* access sec drivers and create a sec model for each one */
> +    sec_managers = virSecurityManagerGetNested(driver->securityManager);
> +    if (sec_managers == NULL) {
> +        goto err_exit;
> +    }
>  
> -    doi = virSecurityManagerGetDOI(driver->securityManager);
> -    model = virSecurityManagerGetModel(driver->securityManager);
> +    /* calculate length */
> +    for (i = 0; sec_managers[i]; i++)
> +        ;
> +    caps->host.nsecModels = i;
>  
> -    if (VIR_ALLOC(caps->host.secModels) < 0) {
> +    if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
>          goto no_memory;
> -    }
>  
> -    if (STRNEQ(model, "none")) {
> -        if (!(caps->host.secModels[0].model = strdup(model)))
> +    for (i = 0; sec_managers[i]; i++) {
> +        doi = virSecurityManagerGetDOI(sec_managers[i]);
> +        model = virSecurityManagerGetModel(sec_managers[i]);
> +        if (!(caps->host.secModels[i].model = strdup(model)))
>              goto no_memory;
> -        if (!(caps->host.secModels[0].doi = strdup(doi)))
> +        if (!(caps->host.secModels[i].doi = strdup(doi)))
>              goto no_memory;
> +        VIR_DEBUG("Initialized caps for security driver \"%s\" with "
> +                  "DOI \"%s\"", model, doi);
>      }
> -
> -    VIR_DEBUG("Initialized caps for security driver \"%s\" with "
> -              "DOI \"%s\"", model, doi);
> +    VIR_FREE(sec_managers);
>  
>      return caps;
>  
>  no_memory:
>      virReportOOMError();
>  err_exit:
> +    VIR_FREE(sec_managers);
>      virCapabilitiesFree(caps);
>      return NULL;
>  }
> @@ -4035,9 +4046,9 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn,
>      qemuDriverLock(driver);
>      memset(secmodel, 0, sizeof(*secmodel));
>  
> -    /* NULL indicates no driver, which we treat as
> -     * success, but simply return no data in *secmodel */
> -    if (driver->caps->host.secModels[0].model == NULL)
> +    /* We treat no driver as success, but simply return no data in *secmodel */
> +    if (driver->caps->host.nsecModels == 0 ||
> +        driver->caps->host.secModels[0].model == NULL)
>          goto cleanup;
>  
>      p = driver->caps->host.secModels[0].model;
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index e9a41df..7fbe412 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -4079,12 +4079,12 @@ void qemuProcessStop(struct qemud_driver *driver,
>      virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
>  
>      /* Clear out dynamically assigned labels */
> -    if (vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
> -        if (!vm->def->seclabels[0]->baselabel)
> -            VIR_FREE(vm->def->seclabels[0]->model);
> -        VIR_FREE(vm->def->seclabels[0]->label);
> +    for (i = 0; i < vm->def->nseclabels; i++) {
> +        if (vm->def->seclabels[i]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
> +            VIR_FREE(vm->def->seclabels[i]->label);
> +        }
> +        VIR_FREE(vm->def->seclabels[i]->imagelabel);
>      }
> -    VIR_FREE(vm->def->seclabels[0]->imagelabel);
>  
>      virDomainDefClearDeviceAliases(vm->def);
>      if (!priv->persistentAddrs) {
> @@ -4188,6 +4188,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
>                        virDomainChrSourceDefPtr monConfig,
>                        bool monJSON)
>  {
> +    size_t i;
>      char ebuf[1024];
>      int logfile = -1;
>      char *timestamp;
> @@ -4195,6 +4196,9 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
>      bool running = true;
>      virDomainPausedReason reason;
>      virSecurityLabelPtr seclabel = NULL;
> +    virSecurityLabelDefPtr seclabeldef = NULL;
> +    virSecurityManagerPtr* sec_managers;

sec_managers = NULL; As you need VIR_FREE(sec_managers); in the end it's
better to initialize it to NULL rather than freeing a random address.

> +    const char *model;
>  
>      VIR_DEBUG("Beginning VM attach process");
>  
> @@ -4227,17 +4231,35 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
>          goto no_memory;
>  
>      VIR_DEBUG("Detect security driver config");
> -    vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_STATIC;
> -    if (VIR_ALLOC(seclabel) < 0)
> -        goto no_memory;
> -    if (virSecurityManagerGetProcessLabel(driver->securityManager,
> -                                          vm->def, vm->pid, seclabel) < 0)
> +    sec_managers = virSecurityManagerGetNested(driver->securityManager);

Don't forget to VIR_FREE() in the end.

> +    if (sec_managers == NULL) {
>          goto cleanup;
> -    if (driver->caps->host.secModels[0].model &&
> -        !(vm->def->seclabels[0]->model = strdup(driver->caps->host.secModels[0].model)))
> -        goto no_memory;
> -    if (!(vm->def->seclabels[0]->label = strdup(seclabel->label)))
> -        goto no_memory;
> +    }
> +
> +    for (i = 0; sec_managers[i]; i++) {
> +        model = virSecurityManagerGetModel(sec_managers[i]);
> +        seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model);
> +        if (seclabeldef == NULL) {
> +            goto cleanup;
> +        }
> +        seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC;
> +        if (VIR_ALLOC(seclabel) < 0)
> +            goto no_memory;
> +        if (virSecurityManagerGetProcessLabel(driver->securityManager,
> +                                              vm->def, vm->pid, seclabel) < 0)
> +            goto cleanup;
> +
> +        //if (driver->caps->host.secModel.model &&
> +        //    !(seclabeldef.model = strdup(driver->caps->host.secModel.model)))
> +        //    goto no_memory;

Probably a leftover from debugging. Besides, we don't support // style
of comments, but rather old c89 style /* */

> +        if (!(seclabeldef->model = strdup(model)))
> +            goto no_memory;
> +
> +        if (!(seclabeldef->label = strdup(seclabel->label)))
> +            goto no_memory;
> +        VIR_FREE(seclabel);
> +        seclabel = NULL;

This is redundant. VIR_FREE() sets passed pointer to NULL.

> +    }
>  
>      VIR_DEBUG("Creating domain log file");
>      if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
> @@ -4359,7 +4381,6 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
>      }
>  
>      VIR_FORCE_CLOSE(logfile);
> -    VIR_FREE(seclabel);

This change is odd as it makes seclabel leak.

>  
>      return 0;
>  
> diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
> index 62af3c6..8639e16 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 9182b39..18be55a 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;
> +
> +    if (virStrToLong_ui(label, &endptr, 10, &uid) ||
> +        endptr == NULL || *endptr != ':') {
> +        return -1;
> +    }
> +
> +    if (virStrToLong_ui(endptr + 1, NULL, 10, &gid))
> +        return -1;
> +
> +    if (uidPtr)
> +        *uidPtr = uid;
> +    if (gidPtr)
> +        *gidPtr = gid;
> +    return 0;
> +}
> +
> +static
> +int virSecurityDACParseIds(virDomainDefPtr def, uid_t *uidPtr, gid_t *gidPtr)
> +{
> +    uid_t uid;
> +    gid_t gid;
> +    virSecurityLabelDefPtr seclabel;
> +
> +    if (def == NULL)
> +        return -1;
> +
> +    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
> +    if (seclabel == NULL) {
> +        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 "
> +                                 "security 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 "
> +                                 "security 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;
> +
> +    if (virSecurityDACGetImageIds(def, priv, &user, &group))
> +        return -1;
>  
> -    return virSecurityDACSetOwnership(path, priv->user, priv->group);
> +    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;
>  
> -    return virSecurityDACSetOwnership(file, priv->user, priv->group);
> +    if (virSecurityDACGetIds(def, priv, &user, &group))
> +        return -1;
> +
> +    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 (virAsprintf(&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 = {
>      .privateDataLen                     = sizeof(virSecurityDACData),
> -    .name                               = "virDAC",
> +    .name                               = SECURITY_DAC_NAME,
>      .probe                              = virSecurityDACProbe,
>      .open                               = virSecurityDACOpen,
>      .close                              = virSecurityDACClose,
> diff --git a/src/security/security_manager.c b/src/security/security_manager.c
> index 5ca3201..970bfd5 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->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT) {
> -        if (mgr->defaultConfined)
> -            vm->seclabels[0]->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
> -        else
> -            vm->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;
> -    }
> +    int rc = 0;
> +    size_t i;
> +    virSecurityManagerPtr* sec_managers = NULL;
> +    virSecurityLabelDefPtr seclabel;
>  
> -    if ((vm->seclabels[0]->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;

Again, sec_managers needs to be freed.

>  
> -    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->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
> +
> +    if (mgr == NULL || mgr->drv == NULL)
> +        return 0;
> +
>      /* NULL model == dynamic labelling, with whatever driver
>       * is active, so we can short circuit verify check to
>       * avoid drivers de-referencing NULLs by accident
>       */
> -    if (!secdef->model)
> +    secdef = virDomainDefGetSecurityLabelDef(def, mgr->drv->name);
> +    if (secdef == NULL || secdef->model == NULL)
>          return 0;
>  
>      if (mgr->drv->domainSecurityVerify)
> @@ -435,3 +472,22 @@ char *virSecurityManagerGetMountOptions(virSecurityManagerPtr mgr,
>      */
>      return NULL;
>  }
> +
> +virSecurityManagerPtr*
> +virSecurityManagerGetNested(virSecurityManagerPtr mgr)
> +{
> +    virSecurityManagerPtr* list = NULL;
> +
> +    if (STREQ("stack", mgr->drv->name)) {
> +        return virSecurityStackGetNested(mgr);
> +    }
> +
> +    if (VIR_ALLOC_N(list, 2) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    list[0] = mgr;
> +    list[1] = NULL;
> +    return list;
> +}
> 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 9a708b1..dc05910 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->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
> -        !def->seclabels[0]->baselabel &&
> -        def->seclabels[0]->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->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
> -        def->seclabels[0]->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->seclabels[0]->imagelabel) {
> +    if (seclabel->imagelabel) {
>          virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
>                                 "%s", _("security image label already defined for VM"));
>          return rc;
>      }
>  
> -    if (def->seclabels[0]->model &&
> -        STRNEQ(def->seclabels[0]->model, SECURITY_SELINUX_NAME)) {
> +    if (seclabel->model &&
> +        STRNEQ(seclabel->model, SECURITY_SELINUX_NAME)) {
>          virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
>                                 _("security label model %s is not supported with selinux"),
> -                               def->seclabels[0]->model);
> +                               seclabel->model);
>          return rc;
>      }
>  
> -    VIR_DEBUG("SELinuxGenSecurityLabel %d", def->seclabels[0]->type);
> +    VIR_DEBUG("SELinuxGenSecurityLabel %d", seclabel->type);
>  
> -    switch (def->seclabels[0]->type) {
> +    switch (seclabel->type) {
>      case VIR_DOMAIN_SECLABEL_STATIC:
> -        if (!(ctx = context_new(def->seclabels[0]->label)) ) {
> +        if (!(ctx = context_new(seclabel->label)) ) {
>              virReportSystemError(errno,
>                                   _("unable to allocate socket security context '%s'"),
> -                                 def->seclabels[0]->label);
> +                                 seclabel->label);
>              return rc;
>          }
>  
> @@ -345,11 +351,11 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
>              }
>          } while (mcsAdd(mcs) == -1);
>  
> -        def->seclabels[0]->label =
> -            SELinuxGenNewContext(def->seclabels[0]->baselabel ?
> -                                 def->seclabels[0]->baselabel :
> +        seclabel->label =
> +            SELinuxGenNewContext(seclabel->baselabel ?
> +                                 seclabel->baselabel :
>                                   data->domain_context, mcs);
> -        if (! def->seclabels[0]->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->seclabels[0]->type));
> +                               virDomainSeclabelTypeToString(seclabel->type));
>          goto cleanup;
>      }
>  
> -    if (!def->seclabels[0]->norelabel) {
> -        def->seclabels[0]->imagelabel = SELinuxGenNewContext(data->file_context, mcs);
> -        if (!def->seclabels[0]->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->seclabels[0]->model &&
> -        !(def->seclabels[0]->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->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
> -            VIR_FREE(def->seclabels[0]->label);
> -        VIR_FREE(def->seclabels[0]->imagelabel);
> -        if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
> -            !def->seclabels[0]->baselabel)
> -            VIR_FREE(def->seclabels[0]->model);
> +        if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
> +            VIR_FREE(seclabel->label);
> +        VIR_FREE(seclabel->imagelabel);
> +        if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
> +            !seclabel->baselabel)
> +            VIR_FREE(seclabel->model);
>      }
>  
>      if (ctx)
> @@ -400,10 +406,10 @@ cleanup:
>      VIR_FREE(mcs);
>  
>      VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
> -              NULLSTR(def->seclabels[0]->model),
> -              NULLSTR(def->seclabels[0]->label),
> -              NULLSTR(def->seclabels[0]->imagelabel),
> -              NULLSTR(def->seclabels[0]->baselabel));
> +              NULLSTR(seclabel->model),
> +              NULLSTR(seclabel->label),
> +              NULLSTR(seclabel->imagelabel),
> +              NULLSTR(seclabel->baselabel));
>  
>      return rc;
>  }
> @@ -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->seclabels[0]->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->seclabels[0];
> +    virSecurityLabelDefPtr seclabel;
> +    virSecurityDeviceLabelDefPtr disk_seclabel;
>  
> -    if (secdef->norelabel || (disk->seclabels[0] && disk->seclabels[0]->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->seclabels[0] && disk->seclabels[0]->norelabel)
> +    disk_seclabel = virDomainDiskDefGetSecurityLabelDef(disk,
> +                                                        SECURITY_SELINUX_NAME);
> +
> +    if (disk_seclabel && disk_seclabel->norelabel)
>          return 0;
>  
> -    if (disk->seclabels[0] && !disk->seclabels[0]->norelabel &&
> -        disk->seclabels[0]->label) {
> -        ret = SELinuxSetFilecon(path, disk->seclabels[0]->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->seclabels[0]) {
> +    if (ret == 1 && !disk_seclabel) {
>          /* If we failed to set a label, but virt_use_nfs let us
>           * proceed anyway, then we don't need to relabel later.  */
> -        if (VIR_ALLOC(disk->seclabels[0]) < 0) {
> +        if (VIR_ALLOC(disk_seclabel) < 0) {
>              virReportOOMError();
>              return -1;
>          }
> -        disk->seclabels[0]->norelabel = true;
> +        disk_seclabel->norelabel = true;
>          ret = 0;
>      }
>      return ret;
> @@ -807,11 +830,15 @@ SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
>                               virDomainDiskDefPtr disk)
>  
>  {
> +    bool allowDiskFormatProbing;
>      virSecuritySELinuxCallbackData cbdata;
> -    cbdata.secdef = def->seclabels[0];
>      cbdata.manager = mgr;
> +    cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
>  
> -    bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
> +    allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
> +
> +    if (cbdata.secdef == NULL)
> +        return -1;
>  
>      if (cbdata.secdef->norelabel)
>          return 0;
> @@ -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->seclabels[0];
>  
> +    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->seclabels[0];
> +
> +    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->seclabels[0];
> +    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->seclabels[0];
> +    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->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
>      char *in = NULL, *out = NULL;
>      int ret = -1;
>  
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
> +
>      if (secdef->norelabel)
>          return 0;
>  
> @@ -1028,10 +1074,14 @@ SELinuxRestoreSecurityChardevLabel(virDomainDefPtr def,
>                                     virDomainChrSourceDefPtr dev)
>  
>  {
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
>      char *in = NULL, *out = NULL;
>      int ret = -1;
>  
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
> +
>      if (secdef->norelabel)
>          return 0;
>  
> @@ -1121,12 +1171,16 @@ SELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
>                                 virDomainDefPtr def,
>                                 int migrated ATTRIBUTE_UNUSED)
>  {
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
>      int i;
>      int rc = 0;
>  
>      VIR_DEBUG("Restoring security label on %s", def->name);
>  
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
> +
>      if (secdef->norelabel)
>          return 0;
>  
> @@ -1171,7 +1225,11 @@ static int
>  SELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
>                              virDomainDefPtr def)
>  {
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
> +
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
>  
>      if (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->seclabels[0];
> +    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->seclabels[0];
> +    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->seclabels[0];
> +    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->seclabels[0];
> -    VIR_DEBUG("SELinuxSetSecurityProcessLabel %s", secdef->label);
> +    virSecurityLabelDefPtr secdef;
>  
> -    if (def->seclabels[0]->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->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
>      context_t execcon = NULL;
>      context_t proccon = NULL;
>      security_context_t scon = NULL;
>      int rc = -1;
>  
> -    if (def->seclabels[0]->label == NULL)
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
> +
> +    if (secdef->label == NULL)
>          return 0;
>  
>      if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
> @@ -1350,9 +1429,13 @@ static int
>  SELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr,
>                                virDomainDefPtr vm)
>  {
> -    const virSecurityLabelDefPtr secdef = vm->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
>      int rc = -1;
>  
> +    secdef = virDomainDefGetSecurityLabelDef(vm, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
> +
>      if (secdef->label == NULL)
>          return 0;
>  
> @@ -1388,9 +1471,13 @@ SELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr,
>                                  virDomainDefPtr def)
>  {
>      /* TODO: verify DOI */
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
> +
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
>  
> -    if (def->seclabels[0]->label == NULL)
> +    if (secdef->label == NULL)
>          return 0;
>  
>      if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
> @@ -1466,9 +1553,13 @@ SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
>                             virDomainDefPtr def,
>                             const char *stdin_path)
>  {
> -    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
>      int i;
> +    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityLabelDefPtr secdef;
> +
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
>  
>      if (secdef->norelabel)
>          return 0;
> @@ -1528,7 +1619,11 @@ SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
>                         virDomainDefPtr def,
>                         int fd)
>  {
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
> +
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return -1;
>  
>      if (secdef->imagelabel == NULL)
>          return 0;
> @@ -1538,13 +1633,17 @@ SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
>  
>  static char *genImageLabel(virSecurityManagerPtr mgr,
>                             virDomainDefPtr def) {
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
>      virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
>      const char *range;
>      context_t ctx = NULL;
>      char *label = NULL;
>      const char *mcs = NULL;
>  
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        goto cleanup;
> +
>      if (secdef->label) {
>          ctx = context_new(secdef->label);
>          if (!ctx) {
> @@ -1575,7 +1674,11 @@ cleanup:
>  static char *SELinuxGetSecurityMountOptions(virSecurityManagerPtr mgr,
>                                              virDomainDefPtr def) {
>      char *opts = NULL;
> -    const virSecurityLabelDefPtr secdef = def->seclabels[0];
> +    virSecurityLabelDefPtr secdef;
> +
> +    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
> +    if (secdef == NULL)
> +        return NULL;
>  
>      if (! secdef->imagelabel)
>          secdef->imagelabel = genImageLabel(mgr,def);
> diff --git a/src/security/security_stack.c b/src/security/security_stack.c
> index 65d30d6..a7b8741 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,15 @@ virSecurityStackVerify(virSecurityManagerPtr mgr,
>                         virDomainDefPtr def)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerVerify(priv->primary, def) < 0)
> -        rc = -1;
> -
> -    if (virSecurityManagerVerify(priv->secondary, def) < 0)
> -        rc = -1;
> +    for(; item; item = item->next) {
> +        if (virSecurityManagerVerify(item->securityManager, def) < 0) {
> +            rc = -1;
> +            break;
> +        }
> +    }
>  
>      return rc;
>  }
> @@ -108,12 +152,12 @@ static int
>  virSecurityStackGenLabel(virSecurityManagerPtr mgr,
>                           virDomainDefPtr vm)
>  {
> -    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
>      int rc = 0;
>  
> -    if (virSecurityManagerGenLabel(priv->primary, vm) < 0)
> +    if (virSecurityManagerGenLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
>          rc = -1;
>  
> +// TODO
>  #if 0
>      /* We don't allow secondary drivers to generate labels.
>       * This may have to change in the future, but requires
> @@ -133,11 +177,12 @@ static int
>  virSecurityStackReleaseLabel(virSecurityManagerPtr mgr,
>                               virDomainDefPtr vm)
>  {
> -    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
>      int rc = 0;
>  
> -    if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0)
> +    if (virSecurityManagerReleaseLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
>          rc = -1;
> +
> +// TODO
>  #if 0
>      /* XXX See note in GenLabel */
>      if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
> @@ -153,11 +198,11 @@ virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
>                               virDomainDefPtr vm,
>                               pid_t pid)
>  {
> -    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
>      int rc = 0;
>  
> -    if (virSecurityManagerReserveLabel(priv->primary, vm, pid) < 0)
> +    if (virSecurityManagerReserveLabel(virSecurityStackGetPrimary(mgr), vm, pid) < 0)
>          rc = -1;
> +// TODO
>  #if 0
>      /* XXX See note in GenLabel */
>      if (virSecurityManagerReserveLabel(priv->secondary, vm, pid) < 0)
> @@ -174,12 +219,13 @@ virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
>                                        virDomainDiskDefPtr disk)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetImageLabel(priv->secondary, vm, disk) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetImageLabel(priv->primary, vm, disk) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetImageLabel(item->securityManager, vm, disk) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -191,12 +237,13 @@ virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
>                                            virDomainDiskDefPtr disk)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerRestoreImageLabel(priv->secondary, vm, disk) < 0)
> -        rc = -1;
> -    if (virSecurityManagerRestoreImageLabel(priv->primary, vm, disk) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerRestoreImageLabel(item->securityManager, vm, disk) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -209,12 +256,13 @@ virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
>  
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetHostdevLabel(priv->secondary, vm, dev) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetHostdevLabel(priv->primary, vm, dev) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetHostdevLabel(item->securityManager, vm, dev) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -226,12 +274,13 @@ virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
>                                              virDomainHostdevDefPtr dev)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerRestoreHostdevLabel(priv->secondary, vm, dev) < 0)
> -        rc = -1;
> -    if (virSecurityManagerRestoreHostdevLabel(priv->primary, vm, dev) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerRestoreHostdevLabel(item->securityManager, vm, dev) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -243,12 +292,13 @@ virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
>                                      const char *stdin_path)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetAllLabel(priv->secondary, vm, stdin_path) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetAllLabel(priv->primary, vm, stdin_path) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetAllLabel(item->securityManager, vm, stdin_path) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -260,12 +310,13 @@ virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
>                                          int migrated)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerRestoreAllLabel(priv->secondary, vm, migrated) < 0)
> -        rc = -1;
> -    if (virSecurityManagerRestoreAllLabel(priv->primary, vm, migrated) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerRestoreAllLabel(item->securityManager, vm, migrated) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -277,12 +328,13 @@ virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
>                                     const char *savefile)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetSavedStateLabel(priv->secondary, vm, savefile) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetSavedStateLabel(priv->primary, vm, savefile) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetSavedStateLabel(item->securityManager, vm, savefile) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -294,12 +346,13 @@ virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
>                                         const char *savefile)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerRestoreSavedStateLabel(priv->secondary, vm, savefile) < 0)
> -        rc = -1;
> -    if (virSecurityManagerRestoreSavedStateLabel(priv->primary, vm, savefile) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerRestoreSavedStateLabel(item->securityManager, vm, savefile) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -310,12 +363,13 @@ virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
>                                  virDomainDefPtr vm)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetProcessLabel(priv->secondary, vm) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetProcessLabel(priv->primary, vm) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetProcessLabel(item->securityManager, vm) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -326,14 +380,14 @@ virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
>                                  pid_t pid,
>                                  virSecurityLabelPtr seclabel)
>  {
> -    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
>      int rc = 0;
>  
> +// TODO
>  #if 0
>      if (virSecurityManagerGetProcessLabel(priv->secondary, vm, pid, seclabel) < 0)
>          rc = -1;
>  #endif
> -    if (virSecurityManagerGetProcessLabel(priv->primary, vm, pid, seclabel) < 0)
> +    if (virSecurityManagerGetProcessLabel(virSecurityStackGetPrimary(mgr), vm, pid, seclabel) < 0)
>          rc = -1;
>  
>      return rc;
> @@ -345,12 +399,13 @@ virSecurityStackSetDaemonSocketLabel(virSecurityManagerPtr mgr,
>                                       virDomainDefPtr vm)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetDaemonSocketLabel(priv->secondary, vm) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetDaemonSocketLabel(priv->primary, vm) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetDaemonSocketLabel(item->securityManager, vm) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -361,12 +416,13 @@ virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
>                                 virDomainDefPtr vm)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetSocketLabel(priv->secondary, vm) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetSocketLabel(priv->primary, vm) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetSocketLabel(item->securityManager, vm) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -377,12 +433,13 @@ virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
>                                   virDomainDefPtr vm)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerClearSocketLabel(priv->secondary, vm) < 0)
> -        rc = -1;
> -    if (virSecurityManagerClearSocketLabel(priv->primary, vm) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerClearSocketLabel(item->securityManager, vm) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -393,12 +450,13 @@ virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
>                                  int fd)
>  {
>      virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item = priv->itemsHead;
>      int rc = 0;
>  
> -    if (virSecurityManagerSetImageFDLabel(priv->secondary, vm, fd) < 0)
> -        rc = -1;
> -    if (virSecurityManagerSetImageFDLabel(priv->primary, vm, fd) < 0)
> -        rc = -1;
> +    for (; item; item = item->next) {
> +        if (virSecurityManagerSetImageFDLabel(item->securityManager, vm, fd) < 0)
> +            rc = -1;
> +    }
>  
>      return rc;
>  }
> @@ -408,6 +466,29 @@ static char *virSecurityStackGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE
>      return NULL;
>  }
>  
> +virSecurityManagerPtr*
> +virSecurityStackGetNested(virSecurityManagerPtr mgr)
> +{
> +    virSecurityManagerPtr *list = NULL;
> +    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
> +    virSecurityStackItemPtr item;
> +    int len = 0, i = 0;
> +
> +    for (item = priv->itemsHead; item; item = item->next)
> +        len++;
> +
> +    if (VIR_ALLOC_N(list, len + 1) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    for (item = priv->itemsHead; item; item = item->next, i++)
> +        list[i] = item->securityManager;
> +    list[len] = NULL;
> +
> +    return list;
> +}
> +
>  virSecurityDriver virSecurityDriverStack = {
>      .privateDataLen                     = sizeof(virSecurityStackData),
>      .name                               = "stack",
> 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 */
> 

I haven't spotted anything wrong other than outpointed.

Michal


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]