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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list