[libvirt] [PATCH v2 3/5] Update security layer to handle many security labels
Michal Privoznik
mprivozn at redhat.com
Thu Jul 19 12:45:26 UTC 2012
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
More information about the libvir-list
mailing list