diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4d28607ff8..a55fb73e72 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -992,6 +992,7 @@ virSecurityManagerFree; virSecurityManagerGenLabel; virSecurityManagerGetDOI; virSecurityManagerGetModel; +virSecurityManagerGetNested; virSecurityManagerGetProcessLabel; virSecurityManagerNew; virSecurityManagerNewStack; @@ -1010,6 +1011,7 @@ virSecurityManagerSetHostdevLabel; virSecurityManagerSetProcessLabel; virSecurityManagerSetSavedStateLabel; virSecurityManagerSetSocketLabel; +virSecurityManagerStackAddNested; virSecurityManagerVerify; virSecurityManagerGetMountOptions; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6a43bb9d95..9f1d70b0dd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -268,8 +268,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; @@ -291,7 +291,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))) { @@ -316,31 +320,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; } @@ -4063,9 +4074,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 553bf90652..8a9f995918 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 = NULL; + const char *model; VIR_DEBUG("Beginning VM attach process"); @@ -4227,17 +4231,31 @@ 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); + 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 (!(seclabeldef->model = strdup(model))) + goto no_memory; + + if (!(seclabeldef->label = strdup(seclabel->label))) + goto no_memory; + VIR_FREE(seclabel); + } VIR_DEBUG("Creating domain log file"); if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0) @@ -4362,6 +4380,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, VIR_FORCE_CLOSE(logfile); VIR_FREE(seclabel); + VIR_FREE(sec_managers); return 0; @@ -4373,6 +4392,7 @@ cleanup: * pretend we never started it */ VIR_FORCE_CLOSE(logfile); VIR_FREE(seclabel); + VIR_FREE(sec_managers); virDomainChrSourceDefFree(monConfig); return -1; } diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 3385232760..299bba6d32 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -272,9 +272,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; @@ -308,10 +312,14 @@ 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; + } virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot update AppArmor profile " - "\'%s\'"), + _("cannot update AppArmor profile \'%s\'"), secdef->imagelabel); return -1; } @@ -326,10 +334,14 @@ 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; + } virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot update AppArmor profile " - "\'%s\'"), + _("cannot update AppArmor profile \'%s\'"), secdef->imagelabel); return -1; } @@ -408,18 +420,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) { virReportError(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)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); @@ -429,31 +446,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) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot load AppArmor profile " - "\'%s\'"), def->seclabel.label); + "\'%s\'"), secdef->label); goto err; } @@ -461,9 +478,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); @@ -475,7 +492,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 @@ -528,7 +550,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); @@ -543,8 +568,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) { @@ -562,9 +591,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; @@ -631,9 +664,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; @@ -676,7 +713,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) { @@ -704,9 +745,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; @@ -766,7 +811,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; @@ -799,7 +849,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 f398c3fa68..e37b09e2a7 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,134 @@ 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("security label for DAC not found in domain %s"), + def->name); + return -1; + } + + if (seclabel->label && parseIds(seclabel->label, &uid, &gid)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse uid and gid for DAC " + "security driver: %s"), seclabel->label); + 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("security label for DAC not found in domain %s"), + def->name); + return -1; + } + + if (seclabel->imagelabel + && parseIds(seclabel->imagelabel, &uid, &gid)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse uid and gid for DAC " + "security driver: %s"), seclabel->label); + 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 +214,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 +296,17 @@ virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, size_t depth ATTRIBUTE_UNUSED, void *opaque) { - virSecurityManagerPtr mgr = opaque; + void **params = opaque; + virSecurityManagerPtr mgr = params[0]; + virDomainDefPtr def = params[1]; virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + uid_t user; + gid_t group; - return virSecurityDACSetOwnership(path, priv->user, priv->group); + if (virSecurityDACGetImageIds(def, priv, &user, &group)) + return -1; + + return virSecurityDACSetOwnership(path, user, group); } @@ -180,6 +316,9 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr, virDomainDiskDefPtr disk) { + uid_t user; + gid_t group; + void *params[2]; virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); if (!priv->dynamicOwnership) @@ -188,12 +327,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 +403,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 +422,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 +459,8 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr, if (!usb) goto done; - ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr); + ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, + params); usbFreeDevice(usb); break; } @@ -314,7 +474,8 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr, if (!pci) goto done; - ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr); + ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, + params); pciFreeDevice(pci); break; @@ -404,17 +565,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 +591,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 +721,7 @@ virSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr = opaque; - return virSecurityDACSetChardevLabel(mgr, &dev->source); + return virSecurityDACSetChardevLabel(mgr, def, &dev->source); } @@ -565,6 +732,8 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr, { virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); int i; + uid_t user; + gid_t group; if (!priv->dynamicOwnership) return 0; @@ -591,16 +760,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 +777,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 +809,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; - if (virSetUIDGID(priv->user, priv->group) < 0) + VIR_DEBUG("Dropping privileges of DEF to %u:%u", user, group); + + if (virSetUIDGID(user, group) < 0) return -1; return 0; @@ -656,9 +833,85 @@ 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("invalid security driver")); + return rc; + } + + seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME); + if (seclabel == NULL) { + return rc; + } + + if (seclabel->imagelabel) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("security image label already " + "defined for VM")); + return rc; + } + + if (seclabel->model + && STRNEQ(seclabel->model, SECURITY_DAC_NAME)) { + virReportError(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) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing label for static security " + "driver in domain %s"), def->name); + 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot generate dac user and group id " + "for domain %s"), def->name); + return rc; + } + break; + case VIR_DOMAIN_SECLABEL_NONE: + /* no op */ + break; + default: + virReportError(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) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot generate dac user and group id " + "for domain %s"), def->name); + VIR_FREE(seclabel->label); + seclabel->label = NULL; + return rc; + } + } + } + return 0; } @@ -683,6 +936,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 +986,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 6b372b55da..0e106d5fe6 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,27 +314,52 @@ 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; + int rc = 0; + size_t i; + virSecurityManagerPtr* sec_managers = NULL; + virSecurityLabelDefPtr seclabel; + + if (mgr == NULL || mgr->drv == NULL) + return -1; + + if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL) + 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) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unconfined guests are not allowed on this host")); + rc = -1; + goto cleanup; + } + + if (!sec_managers[i]->drv->domainGenSecurityLabel) { + virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); } else { - vm->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE; - vm->seclabels[0]->norelabel = true; + rc += sec_managers[i]->drv->domainGenSecurityLabel(sec_managers[i], vm); + if (rc) + goto cleanup; } } - if ((vm->seclabels[0]->type == VIR_DOMAIN_SECLABEL_NONE) && - mgr->requireConfined) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Unconfined guests are not allowed on this host")); - return -1; - } - - if (mgr->drv->domainGenSecurityLabel) - return mgr->drv->domainGenSecurityLabel(mgr, vm); - - virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); - return -1; +cleanup: + VIR_FREE(sec_managers); + return rc; } int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr, @@ -399,12 +430,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) @@ -437,3 +473,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 325fc1ea20..7d638068b3 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -34,8 +34,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, @@ -106,4 +107,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 645232bb9e..eea8fbdc63 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -363,46 +363,52 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr, char *scontext = NULL; context_t ctx = NULL; const char *range; - virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); + virSecurityLabelDefPtr seclabel; + virSecuritySELinuxDataPtr data; - VIR_DEBUG("driver=%s", virSecurityManagerGetDriver(mgr)); - if ((def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) && - !def->seclabels[0]->baselabel && - def->seclabels[0]->model) { + if (mgr == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("security model already defined for VM")); + "%s", _("invalid security driver")); return rc; } - if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC && - def->seclabels[0]->label) { + seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); + if (seclabel == NULL) { + return rc; + } + + data = virSecurityManagerGetPrivateData(mgr); + + VIR_DEBUG("label=%s", virSecurityManagerGetDriver(mgr)); + if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC && + seclabel->label) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); return rc; } - if (def->seclabels[0]->imagelabel) { + if (seclabel->imagelabel) { virReportError(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)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("security label model %s is not supported with selinux"), - def->seclabels[0]->model); + seclabel->model); return rc; } - VIR_DEBUG("type%d", def->seclabels[0]->type); + VIR_DEBUG("type=%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; } @@ -421,11 +427,11 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr, if (virSecuritySELinuxMCSAdd(mgr, mcs) < 0) goto cleanup; - def->seclabels[0]->label = - virSecuritySELinuxGenNewContext(def->seclabels[0]->baselabel ? - def->seclabels[0]->baselabel : - data->domain_context, mcs, false); - if (! def->seclabels[0]->label) { + seclabel->label = + virSecuritySELinuxGenNewContext(seclabel->baselabel ? + seclabel->baselabel : + data->domain_context, mcs, false); + if (!seclabel->label) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; @@ -439,23 +445,23 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr, default: virReportError(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 = virSecuritySELinuxGenNewContext(data->file_context, - mcs, - true); - if (!def->seclabels[0]->imagelabel) { + if (!seclabel->norelabel) { + seclabel->imagelabel = virSecuritySELinuxGenNewContext(data->domain_context, + mcs, + true); + if (!seclabel->imagelabel) { virReportError(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; } @@ -464,12 +470,12 @@ virSecuritySELinuxGenSecurityLabel(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) @@ -478,10 +484,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; } @@ -495,8 +501,14 @@ virSecuritySELinuxReserveSecurityLabel(virSecurityManagerPtr mgr, context_t ctx = NULL; const char *mcs; int rv; + virSecurityLabelDefPtr seclabel; - if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_STATIC) + seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); + if (seclabel == NULL) { + return -1; + } + + if (seclabel->type == VIR_DOMAIN_SECLABEL_STATIC) return 0; if (getpidcon(pid, &pctx) == -1) { @@ -800,9 +812,16 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBU 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 @@ -854,17 +873,21 @@ virSecuritySELinuxSetSecurityFileLabel(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 = virSecuritySELinuxSetFilecon(path, disk->seclabels[0]->label); + if (disk_seclabel && !disk_seclabel->norelabel && + disk_seclabel->label) { + ret = virSecuritySELinuxSetFilecon(path, disk_seclabel->label); } else if (depth == 0) { if (disk->shared) { @@ -879,14 +902,14 @@ virSecuritySELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk, } else { ret = virSecuritySELinuxSetFileconOptional(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; @@ -898,11 +921,15 @@ virSecuritySELinuxSetSecurityImageLabel(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; @@ -929,9 +956,12 @@ static int virSecuritySELinuxSetSecurityPCILabel(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 virSecuritySELinuxSetFilecon(file, secdef->imagelabel); } @@ -939,8 +969,12 @@ static int virSecuritySELinuxSetSecurityUSBLabel(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 virSecuritySELinuxSetFilecon(file, secdef->imagelabel); } @@ -951,9 +985,13 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN 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; @@ -1020,9 +1058,13 @@ virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT 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; @@ -1073,10 +1115,14 @@ virSecuritySELinuxSetSecurityChardevLabel(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; @@ -1119,10 +1165,14 @@ virSecuritySELinuxRestoreSecurityChardevLabel(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; @@ -1212,12 +1262,16 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN 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; @@ -1262,7 +1316,11 @@ static int virSecuritySELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr, 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) { @@ -1287,7 +1345,11 @@ virSecuritySELinuxSetSavedStateLabel(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; @@ -1301,7 +1363,11 @@ virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNU 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; @@ -1314,7 +1380,12 @@ static int virSecuritySELinuxSecurityVerify(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)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("security label driver mismatch: " @@ -1339,12 +1410,16 @@ virSecuritySELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr, virDomainDefPtr def) { /* TODO: verify DOI */ - const virSecurityLabelDefPtr secdef = def->seclabels[0]; - VIR_DEBUG("label=%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("label=%s", secdef->label); if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("security label driver mismatch: " @@ -1371,13 +1446,17 @@ virSecuritySELinuxSetSecurityDaemonSocketLabel(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)) { @@ -1441,9 +1520,13 @@ static int virSecuritySELinuxSetSecuritySocketLabel(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; @@ -1479,9 +1562,13 @@ virSecuritySELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr, virDomainDefPtr def) { /* TODO: verify DOI */ - const virSecurityLabelDefPtr secdef = def->seclabels[0]; + 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; if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) { @@ -1557,9 +1644,13 @@ virSecuritySELinuxSetSecurityAllLabel(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; @@ -1619,7 +1710,11 @@ virSecuritySELinuxSetImageFDLabel(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; @@ -1631,13 +1726,17 @@ static char * virSecuritySELinuxGenImageLabel(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) { @@ -1668,7 +1767,11 @@ virSecuritySELinuxGetSecurityMountOptions(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 = virSecuritySELinuxGenImageLabel(mgr,def); diff --git a/src/security/security_stack.c b/src/security/security_stack.c index 65d9dd749d..7dcd626293 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; }; +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) { - virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); - priv->primary = 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 fd0d26f197..6898c03b7f 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 */