The current security driver usage requires horrible code like if (driver->securityDriver && driver->securityDriver->domainSetSecurityHostdevLabel && driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver, vm, hostdev) < 0) This pair of checks for NULL clutters up the code, making the driver calls 2 lines longer than they really need to be. The goal of the patchset is to change the calling convention to simply if (virSecurityManagerSetHostdevLabel(driver->securityDriver, vm, hostdev) < 0) The first check for 'driver->securityDriver' being NULL is removed by introducing a 'no op' security driver that will always be present if no real driver is enabled. This guarentees driver->securityDriver != NULL. The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel' being non-NULL is hidden in a new abstraction called virSecurityManager. This separates the driver callbacks, from main internal API. The addition of a virSecurityManager object, that is separate from the virSecurityDriver struct also allows for security drivers to carry state / configuration information directly. Thus the DAC/Stack drivers from src/qemu which used to pull config from 'struct qemud_driver' can now be moved into the 'src/security' directory and store their config directly. * src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to use new virSecurityManager APIs * src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h: Move into src/security directory * src/security/security_stack.c, src/security/security_stack.h, src/security/security_dac.c, src/security/security_dac.h: Generic versions of previous QEMU specific drivers * src/security/security_apparmor.c, src/security/security_apparmor.h, src/security/security_driver.c, src/security/security_driver.h, src/security/security_selinux.c, src/security/security_selinux.h: Update to take virSecurityManagerPtr object as the first param in all callbacks * src/security/security_nop.c, src/security/security_nop.h: Stub implementation of all security driver APIs. * src/security/security_manager.h, src/security/security_manager.c: New internal API for invoking security drivers --- src/Makefile.am | 12 +- src/libvirt_private.syms | 33 ++- src/qemu/qemu_conf.h | 6 +- src/qemu/qemu_driver.c | 163 ++++------ src/qemu/qemu_hotplug.c | 84 ++--- src/qemu/qemu_security_dac.c | 576 ------------------------------- src/qemu/qemu_security_dac.h | 22 -- src/qemu/qemu_security_stacked.c | 418 ---------------------- src/qemu/qemu_security_stacked.h | 22 -- src/security/security_apparmor.c | 152 ++++++--- src/security/security_apparmor.h | 2 + src/security/security_dac.c | 703 ++++++++++++++++++++++++++++++++++++++ src/security/security_dac.h | 27 ++ src/security/security_driver.c | 116 ++----- src/security/security_driver.h | 95 +++--- src/security/security_manager.c | 291 ++++++++++++++++ src/security/security_manager.h | 74 ++++ src/security/security_nop.c | 168 +++++++++ src/security/security_nop.h | 17 + src/security/security_selinux.c | 145 +++++--- src/security/security_selinux.h | 2 +- src/security/security_stack.c | 383 +++++++++++++++++++++ src/security/security_stack.h | 24 ++ 23 files changed, 2067 insertions(+), 1468 deletions(-) delete mode 100644 src/qemu/qemu_security_dac.c delete mode 100644 src/qemu/qemu_security_dac.h delete mode 100644 src/qemu/qemu_security_stacked.c delete mode 100644 src/qemu/qemu_security_stacked.h create mode 100644 src/security/security_dac.c create mode 100644 src/security/security_dac.h create mode 100644 src/security/security_manager.c create mode 100644 src/security/security_manager.h create mode 100644 src/security/security_nop.c create mode 100644 src/security/security_nop.h create mode 100644 src/security/security_stack.c create mode 100644 src/security/security_stack.h diff --git a/src/Makefile.am b/src/Makefile.am index c13724a..f8b8434 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -288,11 +288,7 @@ QEMU_DRIVER_SOURCES = \ qemu/qemu_monitor_json.h \ qemu/qemu_driver.c qemu/qemu_driver.h \ qemu/qemu_bridge_filter.c \ - qemu/qemu_bridge_filter.h \ - qemu/qemu_security_stacked.h \ - qemu/qemu_security_stacked.c \ - qemu/qemu_security_dac.h \ - qemu/qemu_security_dac.c + qemu/qemu_bridge_filter.h XENAPI_DRIVER_SOURCES = \ xenapi/xenapi_driver.c xenapi/xenapi_driver.h \ @@ -390,7 +386,11 @@ NWFILTER_DRIVER_SOURCES = \ # Security framework and drivers for various models SECURITY_DRIVER_SOURCES = \ - security/security_driver.h security/security_driver.c + security/security_driver.h security/security_driver.c \ + security/security_nop.h security/security_nop.c \ + security/security_stack.h security/security_stack.c \ + security/security_dac.h security/security_dac.c \ + security/security_manager.h security/security_manager.c SECURITY_DRIVER_SELINUX_SOURCES = \ security/security_selinux.h security/security_selinux.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 19e581c..279559b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -701,13 +701,32 @@ virSecretDefParseFile; virSecretDefParseString; -# security.h -virSecurityDriverGetDOI; -virSecurityDriverGetModel; -virSecurityDriverInit; -virSecurityDriverSetDOI; -virSecurityDriverStartup; -virSecurityDriverVerify; +# security_driver.h +virSecurityDriverLookup; + + +# security_manager.h +virSecurityManagerClearSocketLabel; +virSecurityManagerGenLabel; +virSecurityManagerGetDOI; +virSecurityManagerGetModel; +virSecurityManagerGetProcessLabel; +virSecurityManagerNew; +virSecurityManagerNewStack; +virSecurityManagerNewDAC; +virSecurityManagerReleaseLabel; +virSecurityManagerReserveLabel; +virSecurityManagerRestoreImageLabel; +virSecurityManagerRestoreAllLabel; +virSecurityManagerRestoreHostdevLabel; +virSecurityManagerRestoreSavedStateLabel; +virSecurityManagerSetAllLabel; +virSecurityManagerSetImageLabel; +virSecurityManagerSetHostdevLabel; +virSecurityManagerSetProcessLabel; +virSecurityManagerSetSavedStateLabel; +virSecurityManagerSetSocketLabel; +virSecurityManagerVerify; # storage_conf.h diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 83ddedd..5a5748b 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -35,7 +35,7 @@ # include "domain_conf.h" # include "domain_event.h" # include "threads.h" -# include "security/security_driver.h" +# include "security/security_manager.h" # include "cgroup.h" # include "pci.h" # include "cpu_conf.h" @@ -114,9 +114,7 @@ struct qemud_driver { int domainEventDispatching; char *securityDriverName; - virSecurityDriverPtr securityDriver; - virSecurityDriverPtr securityPrimaryDriver; - virSecurityDriverPtr securitySecondaryDriver; + virSecurityManagerPtr securityManager; char *saveImageFormat; char *dumpImageFormat; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e915705..0f84bb2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -73,8 +73,6 @@ #include "pci.h" #include "hostusb.h" #include "processinfo.h" -#include "qemu_security_stacked.h" -#include "qemu_security_dac.h" #include "libvirt_internal.h" #include "xml.h" #include "cpu/cpu.h" @@ -861,10 +859,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) qemuDomainObjPrivatePtr priv = vm->privateData; int ret = -1; - if (driver->securityDriver && - driver->securityDriver->domainSetSecuritySocketLabel && - driver->securityDriver->domainSetSecuritySocketLabel - (driver->securityDriver,vm) < 0) { + if (virSecurityManagerSetSocketLabel(driver->securityManager, vm) < 0) { VIR_ERROR(_("Failed to set security context for monitor for %s"), vm->def->name); goto error; @@ -882,10 +877,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) if (priv->mon == NULL) virDomainObjUnref(vm); - if (driver->securityDriver && - driver->securityDriver->domainClearSecuritySocketLabel && - driver->securityDriver->domainClearSecuritySocketLabel - (driver->securityDriver,vm) < 0) { + if (virSecurityManagerClearSocketLabel(driver->securityManager, vm) < 0) { VIR_ERROR(_("Failed to clear security context for monitor for %s"), vm->def->name); goto error; @@ -954,10 +946,7 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq goto error; } - if (driver->securityDriver && - driver->securityDriver->domainReserveSecurityLabel && - driver->securityDriver->domainReserveSecurityLabel(driver->securityDriver, - obj) < 0) + if (virSecurityManagerReserveLabel(driver->securityManager, obj) < 0) goto error; if (qemudVMFiltersInstantiate(conn, obj->def)) @@ -995,32 +984,26 @@ qemuReconnectDomains(virConnectPtr conn, struct qemud_driver *driver) static int -qemudSecurityInit(struct qemud_driver *qemud_drv) +qemudSecurityInit(struct qemud_driver *driver) { - int ret; - virSecurityDriverPtr security_drv; - - qemuSecurityStackedSetDriver(qemud_drv); - qemuSecurityDACSetDriver(qemud_drv); - - ret = virSecurityDriverStartup(&security_drv, - qemud_drv->securityDriverName, - qemud_drv->allowDiskFormatProbing); - if (ret == -1) { - VIR_ERROR0(_("Failed to start security driver")); + virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName, + driver->allowDiskFormatProbing); + if (!mgr) return -1; - } - /* No primary security driver wanted to be enabled: just setup - * the DAC driver on its own */ - if (ret == -2) { - qemud_drv->securityDriver = &qemuDACSecurityDriver; - VIR_INFO0(_("No security driver available")); + if (driver->privileged) { + virSecurityManagerPtr dac = virSecurityManagerNewDAC(driver->user, + driver->group, + driver->allowDiskFormatProbing, + driver->dynamicOwnership); + if (!dac) + return -1; + + if (!(driver->securityManager = virSecurityManagerNewStack(mgr, + dac))) + return -1; } else { - qemud_drv->securityPrimaryDriver = security_drv; - qemud_drv->securitySecondaryDriver = &qemuDACSecurityDriver; - qemud_drv->securityDriver = &qemuStackedSecurityDriver; - VIR_INFO("Initialized security driver %s", security_drv->name); + driver->securityManager = mgr; } return 0; @@ -1057,20 +1040,22 @@ qemuCreateCapabilities(virCapsPtr oldcaps, } /* Security driver data */ - if (driver->securityPrimaryDriver) { - const char *doi, *model; + const char *doi, *model; - doi = virSecurityDriverGetDOI(driver->securityPrimaryDriver); - model = virSecurityDriverGetModel(driver->securityPrimaryDriver); + doi = virSecurityManagerGetDOI(driver->securityManager); + model = virSecurityManagerGetModel(driver->securityManager); + if (STREQ(model, "none")) { + model = ""; + doi = ""; + } - if (!(caps->host.secModel.model = strdup(model))) - goto no_memory; - if (!(caps->host.secModel.doi = strdup(doi))) - goto no_memory; + if (!(caps->host.secModel.model = strdup(model))) + goto no_memory; + if (!(caps->host.secModel.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); return caps; @@ -1555,7 +1540,6 @@ qemudShutdown(void) { VIR_FREE(qemu_driver->spicePassword); VIR_FREE(qemu_driver->hugetlbfs_mount); VIR_FREE(qemu_driver->hugepage_path); - VIR_FREE(qemu_driver->securityDriverName); VIR_FREE(qemu_driver->saveImageFormat); VIR_FREE(qemu_driver->dumpImageFormat); @@ -2573,9 +2557,7 @@ static int qemudSecurityHook(void *data) { if (qemudInitCpuAffinity(h->vm) < 0) return -1; - if (h->driver->securityDriver && - h->driver->securityDriver->domainSetSecurityProcessLabel && - h->driver->securityDriver->domainSetSecurityProcessLabel(h->driver->securityDriver, h->vm) < 0) + if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm) < 0) return -1; return 0; @@ -2660,22 +2642,16 @@ static int qemudStartVMDaemon(virConnectPtr conn, /* If you are using a SecurityDriver with dynamic labelling, then generate a security label for isolation */ DEBUG0("Generating domain security label (if required)"); - if (driver->securityDriver && - driver->securityDriver->domainGenSecurityLabel) { - ret = driver->securityDriver->domainGenSecurityLabel(driver->securityDriver, - vm); - qemuDomainSecurityLabelAudit(vm, ret >= 0); - if (ret < 0) - goto cleanup; + if (virSecurityManagerGenLabel(driver->securityManager, vm) < 0) { + qemuDomainSecurityLabelAudit(vm, false); + goto cleanup; } + qemuDomainSecurityLabelAudit(vm, true); DEBUG0("Generating setting domain security labels (if required)"); - if (driver->securityDriver && - driver->securityDriver->domainSetSecurityAllLabel && - driver->securityDriver->domainSetSecurityAllLabel(driver->securityDriver, - vm, stdin_path) < 0) { + if (virSecurityManagerSetAllLabel(driver->securityManager, + vm, stdin_path) < 0) goto cleanup; - } /* Ensure no historical cgroup for this VM is lying around bogus * settings */ @@ -3057,14 +3033,9 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, } /* Reset Security Labels */ - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityAllLabel) - driver->securityDriver->domainRestoreSecurityAllLabel(driver->securityDriver, - vm, migrated); - if (driver->securityDriver && - driver->securityDriver->domainReleaseSecurityLabel) - driver->securityDriver->domainReleaseSecurityLabel(driver->securityDriver, - vm); + virSecurityManagerRestoreAllLabel(driver->securityManager, + vm, migrated); + virSecurityManagerReleaseLabel(driver->securityManager, vm); /* Clear out dynamically assigned labels */ if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { @@ -3568,7 +3539,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; - if (virSecurityDriverVerify(def) < 0) + if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) @@ -4471,10 +4442,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, } if ((!bypassSecurityDriver) && - driver->securityDriver && - driver->securityDriver->domainSetSavedStateLabel && - driver->securityDriver->domainSetSavedStateLabel(driver->securityDriver, - vm, path) == -1) + virSecurityManagerSetSavedStateLabel(driver->securityManager, + vm, path) < 0) goto endjob; if (header.compressed == QEMUD_SAVE_FORMAT_RAW) { @@ -4507,10 +4476,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, goto endjob; if ((!bypassSecurityDriver) && - driver->securityDriver && - driver->securityDriver->domainRestoreSavedStateLabel && - driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, - vm, path) == -1) + virSecurityManagerRestoreSavedStateLabel(driver->securityManager, + vm, path) < 0) VIR_WARN("failed to restore save state label on %s", path); if (cgroup != NULL) { @@ -4552,10 +4519,8 @@ endjob: } if ((!bypassSecurityDriver) && - driver->securityDriver && - driver->securityDriver->domainRestoreSavedStateLabel && - driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, - vm, path) == -1) + virSecurityManagerRestoreSavedStateLabel(driver->securityManager, + vm, path) < 0) VIR_WARN("failed to restore save state label on %s", path); } @@ -4779,10 +4744,8 @@ static int doCoreDump(struct qemud_driver *driver, goto cleanup; } - if (driver->securityDriver && - driver->securityDriver->domainSetSavedStateLabel && - driver->securityDriver->domainSetSavedStateLabel(driver->securityDriver, - vm, path) == -1) + if (virSecurityManagerSetSavedStateLabel(driver->securityManager, + vm, path) < 0) goto cleanup; qemuDomainObjEnterMonitorWithDriver(driver, vm); @@ -4814,10 +4777,8 @@ static int doCoreDump(struct qemud_driver *driver, if (ret < 0) goto cleanup; - if (driver->securityDriver && - driver->securityDriver->domainRestoreSavedStateLabel && - driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, - vm, path) == -1) + if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager, + vm, path) < 0) goto cleanup; cleanup: @@ -5434,10 +5395,8 @@ static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr sec * QEMU monitor hasn't seen SIGHUP/ERR on poll(). */ if (virDomainObjIsActive(vm)) { - if (driver->securityDriver && - driver->securityDriver->domainGetSecurityProcessLabel && - driver->securityDriver->domainGetSecurityProcessLabel(driver->securityDriver, - vm, seclabel) < 0) { + if (virSecurityManagerGetProcessLabel(driver->securityManager, + vm, seclabel) < 0) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to get security label")); goto cleanup; @@ -5461,10 +5420,6 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn, int ret = 0; qemuDriverLock(driver); - if (!driver->securityPrimaryDriver) { - memset(secmodel, 0, sizeof (*secmodel)); - goto cleanup; - } p = driver->caps->host.secModel.model; if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) { @@ -5840,10 +5795,8 @@ qemudDomainSaveImageStartVM(virConnectPtr conn, ret = 0; out: - if (driver->securityDriver && - driver->securityDriver->domainRestoreSavedStateLabel && - driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, - vm, path) == -1) + if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager, + vm, path) < 0) VIR_WARN("failed to restore save state label on %s", path); return ret; @@ -6372,7 +6325,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { VIR_DOMAIN_XML_INACTIVE))) goto cleanup; - if (virSecurityDriverVerify(def) < 0) + if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 827bcaf..1dc036c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -83,10 +83,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, return -1; } - if (driver->securityDriver && - driver->securityDriver->domainSetSecurityImageLabel && - driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerSetImageLabel(driver->securityManager, + vm, disk) < 0) return -1; if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCmdFlags))) @@ -115,10 +113,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, if (ret < 0) goto error; - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, origdisk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, origdisk) < 0) VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src); VIR_FREE(origdisk->src); @@ -134,10 +130,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, error: VIR_FREE(driveAlias); - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, disk) < 0) VIR_WARN("Unable to restore security label on new media %s", disk->src); return -1; } @@ -162,10 +156,8 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, } } - if (driver->securityDriver && - driver->securityDriver->domainSetSecurityImageLabel && - driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerSetImageLabel(driver->securityManager, + vm, disk) < 0) return -1; if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { @@ -232,10 +224,8 @@ error: qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0) VIR_WARN("Unable to release PCI address on %s", disk->src); - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, disk) < 0) VIR_WARN("Unable to restore security label on %s", disk->src); return -1; @@ -375,10 +365,8 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver, } - if (driver->securityDriver && - driver->securityDriver->domainSetSecurityImageLabel && - driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerSetImageLabel(driver->securityManager, + vm, disk) < 0) return -1; /* We should have an address already, so make sure */ @@ -464,10 +452,8 @@ error: VIR_FREE(devstr); VIR_FREE(drivestr); - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, disk) < 0) VIR_WARN("Unable to restore security label on %s", disk->src); return -1; @@ -492,10 +478,8 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, } } - if (driver->securityDriver && - driver->securityDriver->domainSetSecurityImageLabel && - driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerSetImageLabel(driver->securityManager, + vm, disk) < 0) return -1; if (!disk->src) { @@ -551,10 +535,8 @@ error: VIR_FREE(devstr); VIR_FREE(drivestr); - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, disk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, disk) < 0) VIR_WARN("Unable to restore security label on %s", disk->src); return -1; @@ -979,10 +961,8 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver, } - if (driver->securityDriver && - driver->securityDriver->domainSetSecurityHostdevLabel && - driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver, - vm, hostdev) < 0) + if (virSecurityManagerSetHostdevLabel(driver->securityManager, + vm, hostdev) < 0) return -1; switch (hostdev->source.subsys.type) { @@ -1008,10 +988,8 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver, return 0; error: - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityHostdevLabel && - driver->securityDriver->domainRestoreSecurityHostdevLabel(driver->securityDriver, - vm, hostdev) < 0) + if (virSecurityManagerRestoreHostdevLabel(driver->securityManager, + vm, hostdev) < 0) VIR_WARN0("Unable to restore host device labelling on hotplug fail"); return -1; @@ -1183,10 +1161,8 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver, virDomainDiskDefFree(detach); - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, dev->data.disk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, dev->data.disk) < 0) VIR_WARN("Unable to restore security label on %s", dev->data.disk->src); if (cgroup != NULL) { @@ -1263,10 +1239,8 @@ int qemuDomainDetachSCSIDiskDevice(struct qemud_driver *driver, virDomainDiskDefFree(detach); - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityImageLabel && - driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, - vm, dev->data.disk) < 0) + if (virSecurityManagerRestoreImageLabel(driver->securityManager, + vm, dev->data.disk) < 0) VIR_WARN("Unable to restore security label on %s", dev->data.disk->src); if (cgroup != NULL) { @@ -1699,10 +1673,8 @@ int qemuDomainDetachHostDevice(struct qemud_driver *driver, return -1; } - if (driver->securityDriver && - driver->securityDriver->domainRestoreSecurityHostdevLabel && - driver->securityDriver->domainRestoreSecurityHostdevLabel(driver->securityDriver, - vm, dev->data.hostdev) < 0) + if (virSecurityManagerRestoreHostdevLabel(driver->securityManager, + vm, dev->data.hostdev) < 0) VIR_WARN0("Failed to restore host device labelling"); return ret; diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c deleted file mode 100644 index 6b6170a..0000000 --- a/src/qemu/qemu_security_dac.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * QEMU POSIX DAC security driver - */ -#include <config.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include "qemu_security_dac.h" -#include "qemu_conf.h" -#include "datatypes.h" -#include "virterror_internal.h" -#include "util.h" -#include "memory.h" -#include "logging.h" -#include "pci.h" -#include "hostusb.h" -#include "storage_file.h" - -#define VIR_FROM_THIS VIR_FROM_QEMU - -static struct qemud_driver *driver; - -void qemuSecurityDACSetDriver(struct qemud_driver *newdriver) -{ - driver = newdriver; -} - - -static int -qemuSecurityDACSetOwnership(const char *path, int uid, int gid) -{ - VIR_INFO("Setting DAC user and group on '%s' to '%d:%d'", path, uid, gid); - - if (chown(path, uid, gid) < 0) { - struct stat sb; - int chown_errno = errno; - - if (stat(path, &sb) >= 0) { - if (sb.st_uid == uid && - sb.st_gid == gid) { - /* It's alright, there's nothing to change anyway. */ - return 0; - } - } - - if (chown_errno == EOPNOTSUPP) { - VIR_INFO("Setting user and group to '%d:%d' on '%s' not supported by filesystem", - uid, gid, path); - } else if (chown_errno == EPERM) { - VIR_INFO("Setting user and group to '%d:%d' on '%s' not permitted", - uid, gid, path); - } else if (chown_errno == EROFS) { - VIR_INFO("Setting user and group to '%d:%d' on '%s' not possible on readonly filesystem", - uid, gid, path); - } else { - virReportSystemError(chown_errno, - _("unable to set user and group to '%d:%d' on '%s'"), - uid, gid, path); - return -1; - } - } - return 0; -} - -static int -qemuSecurityDACRestoreSecurityFileLabel(const char *path) -{ - struct stat buf; - int rc = -1; - char *newpath = NULL; - - VIR_INFO("Restoring DAC user and group on '%s'", path); - - if (virFileResolveLink(path, &newpath) < 0) { - virReportSystemError(errno, - _("cannot resolve symlink %s"), path); - goto err; - } - - if (stat(newpath, &buf) != 0) - goto err; - - /* XXX record previous ownership */ - rc = qemuSecurityDACSetOwnership(newpath, 0, 0); - -err: - VIR_FREE(newpath); - return rc; -} - - -static int -qemuSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, - const char *path, - size_t depth ATTRIBUTE_UNUSED, - void *opaque ATTRIBUTE_UNUSED) -{ - return qemuSecurityDACSetOwnership(path, driver->user, driver->group); -} - - -static int -qemuSecurityDACSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, - virDomainDiskDefPtr disk) - -{ - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - return virDomainDiskDefForeachPath(disk, - driver->allowDiskFormatProbing, - false, - qemuSecurityDACSetSecurityFileLabel, - NULL); -} - - -static int -qemuSecurityDACRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, - virDomainDiskDefPtr disk, - int migrated) -{ - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - /* Don't restore labels on readoly/shared disks, because - * other VMs may still be accessing these - * Alternatively we could iterate over all running - * domains and try to figure out if it is in use, but - * this would not work for clustered filesystems, since - * we can't see running VMs using the file on other nodes - * Safest bet is thus to skip the restore step. - */ - if (disk->readonly || disk->shared) - return 0; - - if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) - return 0; - - /* If we have a shared FS & doing migrated, we must not - * change ownership, because that kills access on the - * destination host which is sub-optimal for the guest - * VM's I/O attempts :-) - */ - if (migrated) { - int rc = virStorageFileIsSharedFS(disk->src); - if (rc < 0) - return -1; - if (rc == 1) { - VIR_DEBUG("Skipping image label restore on %s because FS is shared", - disk->src); - return 0; - } - } - - return qemuSecurityDACRestoreSecurityFileLabel(disk->src); -} - - -static int -qemuSecurityDACRestoreSecurityImageLabel(virSecurityDriverPtr drv, - virDomainObjPtr vm, - virDomainDiskDefPtr disk) -{ - return qemuSecurityDACRestoreSecurityImageLabelInt(drv, vm, disk, 0); -} - - -static int -qemuSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, - const char *file, - void *opaque ATTRIBUTE_UNUSED) -{ - return qemuSecurityDACSetOwnership(file, driver->user, driver->group); -} - - -static int -qemuSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, - const char *file, - void *opaque ATTRIBUTE_UNUSED) -{ - return qemuSecurityDACSetOwnership(file, driver->user, driver->group); -} - - -static int -qemuSecurityDACSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virDomainHostdevDefPtr dev) - -{ - int ret = -1; - - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - return 0; - - switch (dev->source.subsys.type) { - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { - usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus, - dev->source.subsys.u.usb.device); - - if (!usb) - goto done; - - ret = usbDeviceFileIterate(usb, qemuSecurityDACSetSecurityUSBLabel, vm); - usbFreeDevice(usb); - break; - } - - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: { - pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain, - dev->source.subsys.u.pci.bus, - dev->source.subsys.u.pci.slot, - dev->source.subsys.u.pci.function); - - if (!pci) - goto done; - - ret = pciDeviceFileIterate(pci, qemuSecurityDACSetSecurityPCILabel, vm); - pciFreeDevice(pci); - - break; - } - - default: - ret = 0; - break; - } - -done: - return ret; -} - - -static int -qemuSecurityDACRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, - const char *file, - void *opaque ATTRIBUTE_UNUSED) -{ - return qemuSecurityDACRestoreSecurityFileLabel(file); -} - - -static int -qemuSecurityDACRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, - const char *file, - void *opaque ATTRIBUTE_UNUSED) -{ - return qemuSecurityDACRestoreSecurityFileLabel(file); -} - - -static int -qemuSecurityDACRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, - virDomainHostdevDefPtr dev) - -{ - int ret = -1; - - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - return 0; - - switch (dev->source.subsys.type) { - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { - usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus, - dev->source.subsys.u.usb.device); - - if (!usb) - goto done; - - ret = usbDeviceFileIterate(usb, qemuSecurityDACRestoreSecurityUSBLabel, NULL); - usbFreeDevice(usb); - - break; - } - - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: { - pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain, - dev->source.subsys.u.pci.bus, - dev->source.subsys.u.pci.slot, - dev->source.subsys.u.pci.function); - - if (!pci) - goto done; - - ret = pciDeviceFileIterate(pci, qemuSecurityDACRestoreSecurityPCILabel, NULL); - pciFreeDevice(pci); - - break; - } - - default: - ret = 0; - break; - } - -done: - return ret; -} - - -static int -qemuSecurityDACSetChardevLabel(virDomainObjPtr vm, - virDomainChrDefPtr dev) - -{ - const virSecurityLabelDefPtr secdef = &vm->def->seclabel; - char *in = NULL, *out = NULL; - int ret = -1; - - if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) - return 0; - - switch (dev->type) { - case VIR_DOMAIN_CHR_TYPE_DEV: - case VIR_DOMAIN_CHR_TYPE_FILE: - ret = qemuSecurityDACSetOwnership(dev->data.file.path, driver->user, driver->group); - break; - - case VIR_DOMAIN_CHR_TYPE_PIPE: - if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) || - (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) { - virReportOOMError(); - goto done; - } - if ((qemuSecurityDACSetOwnership(in, driver->user, driver->group) < 0) || - (qemuSecurityDACSetOwnership(out, driver->user, driver->group) < 0)) - goto done; - ret = 0; - break; - - default: - ret = 0; - break; - } - -done: - VIR_FREE(in); - VIR_FREE(out); - return ret; -} - -static int -qemuSecurityDACRestoreChardevLabel(virDomainObjPtr vm, - virDomainChrDefPtr dev) - -{ - const virSecurityLabelDefPtr secdef = &vm->def->seclabel; - char *in = NULL, *out = NULL; - int ret = -1; - - if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) - return 0; - - switch (dev->type) { - case VIR_DOMAIN_CHR_TYPE_DEV: - case VIR_DOMAIN_CHR_TYPE_FILE: - ret = qemuSecurityDACRestoreSecurityFileLabel(dev->data.file.path); - break; - - case VIR_DOMAIN_CHR_TYPE_PIPE: - if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) || - (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) { - virReportOOMError(); - goto done; - } - if ((qemuSecurityDACRestoreSecurityFileLabel(out) < 0) || - (qemuSecurityDACRestoreSecurityFileLabel(in) < 0)) - goto done; - ret = 0; - break; - - default: - ret = 0; - break; - } - -done: - VIR_FREE(in); - VIR_FREE(out); - return ret; -} - - -static int -qemuSecurityDACRestoreChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, - virDomainChrDefPtr dev, - void *opaque) -{ - virDomainObjPtr vm = opaque; - - return qemuSecurityDACRestoreChardevLabel(vm, dev); -} - - -static int -qemuSecurityDACRestoreSecurityAllLabel(virSecurityDriverPtr drv, - virDomainObjPtr vm, - int migrated) -{ - int i; - int rc = 0; - - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - VIR_DEBUG("Restoring security label on %s migrated=%d", - vm->def->name, migrated); - - for (i = 0 ; i < vm->def->nhostdevs ; i++) { - if (qemuSecurityDACRestoreSecurityHostdevLabel(drv, - vm, - vm->def->hostdevs[i]) < 0) - rc = -1; - } - for (i = 0 ; i < vm->def->ndisks ; i++) { - if (qemuSecurityDACRestoreSecurityImageLabelInt(drv, - vm, - vm->def->disks[i], - migrated) < 0) - rc = -1; - } - - if (virDomainChrDefForeach(vm->def, - false, - qemuSecurityDACRestoreChardevCallback, - vm) < 0) - rc = -1; - - if (vm->def->os.kernel && - qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0) - rc = -1; - - if (vm->def->os.initrd && - qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, - virDomainChrDefPtr dev, - void *opaque) -{ - virDomainObjPtr vm = opaque; - - return qemuSecurityDACSetChardevLabel(vm, dev); -} - - -static int -qemuSecurityDACSetSecurityAllLabel(virSecurityDriverPtr drv, - virDomainObjPtr vm, - const char *stdin_path ATTRIBUTE_UNUSED) -{ - int i; - - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - for (i = 0 ; i < vm->def->ndisks ; i++) { - /* XXX fixme - we need to recursively label the entriy tree :-( */ - if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) - continue; - if (qemuSecurityDACSetSecurityImageLabel(drv, - vm, - vm->def->disks[i]) < 0) - return -1; - } - for (i = 0 ; i < vm->def->nhostdevs ; i++) { - if (qemuSecurityDACSetSecurityHostdevLabel(drv, - vm, - vm->def->hostdevs[i]) < 0) - return -1; - } - - if (virDomainChrDefForeach(vm->def, - true, - qemuSecurityDACSetChardevCallback, - vm) < 0) - return -1; - - if (vm->def->os.kernel && - qemuSecurityDACSetOwnership(vm->def->os.kernel, - driver->user, - driver->group) < 0) - return -1; - - if (vm->def->os.initrd && - qemuSecurityDACSetOwnership(vm->def->os.initrd, - driver->user, - driver->group) < 0) - return -1; - - return 0; -} - - -static int -qemuSecurityDACSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, - const char *savefile) -{ - if (!driver->privileged) - return 0; - - return qemuSecurityDACSetOwnership(savefile, driver->user, driver->group); -} - - -static int -qemuSecurityDACRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, - const char *savefile) -{ - if (!driver->privileged || !driver->dynamicOwnership) - return 0; - - return qemuSecurityDACRestoreSecurityFileLabel(savefile); -} - - -static int -qemuSecurityDACSetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED) -{ - DEBUG("Dropping privileges of VM to %d:%d", driver->user, driver->group); - - if (!driver->privileged) - return 0; - - if (virSetUIDGID(driver->user, driver->group) < 0) - return -1; - - return 0; -} - - - -virSecurityDriver qemuDACSecurityDriver = { - .name = "qemuDAC", - - .domainSetSecurityProcessLabel = qemuSecurityDACSetProcessLabel, - - .domainSetSecurityImageLabel = qemuSecurityDACSetSecurityImageLabel, - .domainRestoreSecurityImageLabel = qemuSecurityDACRestoreSecurityImageLabel, - - .domainSetSecurityAllLabel = qemuSecurityDACSetSecurityAllLabel, - .domainRestoreSecurityAllLabel = qemuSecurityDACRestoreSecurityAllLabel, - - .domainSetSecurityHostdevLabel = qemuSecurityDACSetSecurityHostdevLabel, - .domainRestoreSecurityHostdevLabel = qemuSecurityDACRestoreSecurityHostdevLabel, - - .domainSetSavedStateLabel = qemuSecurityDACSetSavedStateLabel, - .domainRestoreSavedStateLabel = qemuSecurityDACRestoreSavedStateLabel, -}; diff --git a/src/qemu/qemu_security_dac.h b/src/qemu/qemu_security_dac.h deleted file mode 100644 index a742f7a..0000000 --- a/src/qemu/qemu_security_dac.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * QEMU POSIX DAC security driver - */ - -#include "security/security_driver.h" -#include "qemu_conf.h" - -#ifndef __QEMU_SECURITY_DAC -# define __QEMU_SECURITY_DAC - -extern virSecurityDriver qemuDACSecurityDriver; - -void qemuSecurityDACSetDriver(struct qemud_driver *driver); - -#endif /* __QEMU_SECURITY_DAC */ diff --git a/src/qemu/qemu_security_stacked.c b/src/qemu/qemu_security_stacked.c deleted file mode 100644 index 432d095..0000000 --- a/src/qemu/qemu_security_stacked.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * QEMU stacked security driver - */ - -#include <config.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include "qemu_security_stacked.h" - -#include "qemu_conf.h" -#include "datatypes.h" -#include "virterror_internal.h" -#include "util.h" -#include "memory.h" -#include "logging.h" -#include "pci.h" -#include "hostusb.h" -#include "storage_file.h" - -#define VIR_FROM_THIS VIR_FROM_QEMU - - -static struct qemud_driver *driver; - -void qemuSecurityStackedSetDriver(struct qemud_driver *newdriver) -{ - driver = newdriver; -} - - -static int -qemuSecurityStackedVerify(virDomainDefPtr def) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSecurityVerify && - driver->securitySecondaryDriver->domainSecurityVerify(def) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSecurityVerify && - driver->securityPrimaryDriver->domainSecurityVerify(def) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedGenLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainGenSecurityLabel && - driver->securitySecondaryDriver->domainGenSecurityLabel(driver->securitySecondaryDriver, - vm) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainGenSecurityLabel && - driver->securityPrimaryDriver->domainGenSecurityLabel(driver->securityPrimaryDriver, - vm) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedReleaseLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainReleaseSecurityLabel && - driver->securitySecondaryDriver->domainReleaseSecurityLabel(driver->securitySecondaryDriver, - vm) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainReleaseSecurityLabel && - driver->securityPrimaryDriver->domainReleaseSecurityLabel(driver->securityPrimaryDriver, - vm) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedReserveLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainReserveSecurityLabel && - driver->securitySecondaryDriver->domainReserveSecurityLabel(driver->securitySecondaryDriver, - vm) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainReserveSecurityLabel && - driver->securityPrimaryDriver->domainReserveSecurityLabel(driver->securityPrimaryDriver, - vm) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virDomainDiskDefPtr disk) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSetSecurityImageLabel && - driver->securitySecondaryDriver->domainSetSecurityImageLabel(driver->securitySecondaryDriver, - vm, disk) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSetSecurityImageLabel && - driver->securityPrimaryDriver->domainSetSecurityImageLabel(driver->securityPrimaryDriver, - vm, disk) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedRestoreSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virDomainDiskDefPtr disk) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainRestoreSecurityImageLabel && - driver->securitySecondaryDriver->domainRestoreSecurityImageLabel(driver->securitySecondaryDriver, - vm, disk) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainRestoreSecurityImageLabel && - driver->securityPrimaryDriver->domainRestoreSecurityImageLabel(driver->securityPrimaryDriver, - vm, disk) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virDomainHostdevDefPtr dev) - -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSetSecurityHostdevLabel && - driver->securitySecondaryDriver->domainSetSecurityHostdevLabel(driver->securitySecondaryDriver, - vm, dev) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSetSecurityHostdevLabel && - driver->securityPrimaryDriver->domainSetSecurityHostdevLabel(driver->securityPrimaryDriver, - vm, dev) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virDomainHostdevDefPtr dev) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel && - driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel(driver->securitySecondaryDriver, - vm, dev) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel && - driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel(driver->securityPrimaryDriver, - vm, dev) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedSetSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *stdin_path) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSetSecurityAllLabel && - driver->securitySecondaryDriver->domainSetSecurityAllLabel(driver->securitySecondaryDriver, - vm, stdin_path) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSetSecurityAllLabel && - driver->securityPrimaryDriver->domainSetSecurityAllLabel(driver->securityPrimaryDriver, - vm, stdin_path) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - int migrated) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainRestoreSecurityAllLabel && - driver->securitySecondaryDriver->domainRestoreSecurityAllLabel(driver->securitySecondaryDriver, - vm, migrated) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainRestoreSecurityAllLabel && - driver->securityPrimaryDriver->domainRestoreSecurityAllLabel(driver->securityPrimaryDriver, - vm, migrated) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *savefile) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSetSavedStateLabel && - driver->securitySecondaryDriver->domainSetSavedStateLabel(driver->securitySecondaryDriver, - vm, savefile) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSetSavedStateLabel && - driver->securityPrimaryDriver->domainSetSavedStateLabel(driver->securityPrimaryDriver, - vm, savefile) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - const char *savefile) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainRestoreSavedStateLabel && - driver->securitySecondaryDriver->domainRestoreSavedStateLabel(driver->securitySecondaryDriver, - vm, savefile) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainRestoreSavedStateLabel && - driver->securityPrimaryDriver->domainRestoreSavedStateLabel(driver->securityPrimaryDriver, - vm, savefile) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedSetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSetSecurityProcessLabel && - driver->securitySecondaryDriver->domainSetSecurityProcessLabel(driver->securitySecondaryDriver, - vm) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSetSecurityProcessLabel && - driver->securityPrimaryDriver->domainSetSecurityProcessLabel(driver->securityPrimaryDriver, - vm) < 0) - rc = -1; - - return rc; -} - -static int -qemuSecurityStackedGetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm, - virSecurityLabelPtr seclabel) -{ - int rc = 0; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainGetSecurityProcessLabel && - driver->securityPrimaryDriver->domainGetSecurityProcessLabel(driver->securityPrimaryDriver, - vm, - seclabel) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedSetSocketLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm) -{ - int rc = 0; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainSetSecuritySocketLabel && - driver->securityPrimaryDriver->domainSetSecuritySocketLabel(driver->securityPrimaryDriver, - vm) < 0) - rc = -1; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainSetSecuritySocketLabel && - driver->securitySecondaryDriver->domainSetSecuritySocketLabel(driver->securitySecondaryDriver, - vm) < 0) - rc = -1; - - return rc; -} - - -static int -qemuSecurityStackedClearSocketLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, - virDomainObjPtr vm) -{ - int rc = 0; - - if (driver->securitySecondaryDriver && - driver->securitySecondaryDriver->domainClearSecuritySocketLabel && - driver->securitySecondaryDriver->domainClearSecuritySocketLabel(driver->securitySecondaryDriver, - vm) < 0) - rc = -1; - - if (driver->securityPrimaryDriver && - driver->securityPrimaryDriver->domainClearSecuritySocketLabel && - driver->securityPrimaryDriver->domainClearSecuritySocketLabel(driver->securityPrimaryDriver, - vm) < 0) - rc = -1; - - return rc; -} - - -virSecurityDriver qemuStackedSecurityDriver = { - .name = "qemuStacked", - .domainSecurityVerify = qemuSecurityStackedVerify, - - .domainGenSecurityLabel = qemuSecurityStackedGenLabel, - .domainReleaseSecurityLabel = qemuSecurityStackedReleaseLabel, - .domainReserveSecurityLabel = qemuSecurityStackedReserveLabel, - - .domainGetSecurityProcessLabel = qemuSecurityStackedGetProcessLabel, - .domainSetSecurityProcessLabel = qemuSecurityStackedSetProcessLabel, - - .domainSetSecurityImageLabel = qemuSecurityStackedSetSecurityImageLabel, - .domainRestoreSecurityImageLabel = qemuSecurityStackedRestoreSecurityImageLabel, - - .domainSetSecurityAllLabel = qemuSecurityStackedSetSecurityAllLabel, - .domainRestoreSecurityAllLabel = qemuSecurityStackedRestoreSecurityAllLabel, - - .domainSetSecurityHostdevLabel = qemuSecurityStackedSetSecurityHostdevLabel, - .domainRestoreSecurityHostdevLabel = qemuSecurityStackedRestoreSecurityHostdevLabel, - - .domainSetSavedStateLabel = qemuSecurityStackedSetSavedStateLabel, - .domainRestoreSavedStateLabel = qemuSecurityStackedRestoreSavedStateLabel, - - .domainClearSecuritySocketLabel = qemuSecurityStackedClearSocketLabel, - .domainSetSecuritySocketLabel = qemuSecurityStackedSetSocketLabel, -}; diff --git a/src/qemu/qemu_security_stacked.h b/src/qemu/qemu_security_stacked.h deleted file mode 100644 index 07f76d5..0000000 --- a/src/qemu/qemu_security_stacked.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * QEMU stacked security driver - */ - -#include "security/security_driver.h" -#include "qemu_conf.h" - -#ifndef __QEMU_SECURITY_STACKED -# define __QEMU_SECURITY_STACKED - -extern virSecurityDriver qemuStackedSecurityDriver; - -void qemuSecurityStackedSetDriver(struct qemud_driver *driver); - -#endif /* __QEMU_SECURITY_DAC */ diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 468d0a3..d82ba73 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -1,4 +1,3 @@ - /* * AppArmor security driver for libvirt * Copyright (C) 2009-2010 Canonical Ltd. @@ -28,7 +27,6 @@ #include "internal.h" -#include "security_driver.h" #include "security_apparmor.h" #include "util.h" #include "memory.h" @@ -47,7 +45,7 @@ /* Data structure to pass to *FileIterate so we have everything we need */ struct SDPDOP { - virSecurityDriverPtr drv; + virSecurityManagerPtr mgr; virDomainObjPtr vm; }; @@ -158,7 +156,7 @@ profile_status_file(const char *str) * load (add) a profile. Will create one if necessary */ static int -load_profile(virSecurityDriverPtr drv, +load_profile(virSecurityManagerPtr mgr, const char *profile, virDomainObjPtr vm, const char *fn, @@ -169,7 +167,7 @@ load_profile(virSecurityDriverPtr drv, char *xml = NULL; int pipefd[2]; pid_t child; - const char *probe = virSecurityDriverGetAllowDiskFormatProbing(drv) + const char *probe = virSecurityManagerGetAllowDiskFormatProbing(mgr) ? "1" : "0"; if (pipe(pipefd) < -1) { @@ -300,7 +298,7 @@ cleanup: * NULL. */ static int -reload_profile(virSecurityDriverPtr drv, +reload_profile(virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *fn, bool append) @@ -317,7 +315,7 @@ reload_profile(virSecurityDriverPtr drv, /* Update the profile only if it is loaded */ if (profile_loaded(secdef->imagelabel) >= 0) { - if (load_profile(drv, secdef->imagelabel, vm, fn, append) < 0) { + if (load_profile(mgr, secdef->imagelabel, vm, fn, append) < 0) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot update AppArmor profile " "\'%s\'"), @@ -340,7 +338,7 @@ AppArmorSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, struct SDPDOP *ptr = opaque; virDomainObjPtr vm = ptr->vm; - if (reload_profile(ptr->drv, vm, file, true) < 0) { + if (reload_profile(ptr->mgr, vm, file, true) < 0) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot update AppArmor profile " @@ -358,7 +356,7 @@ AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, struct SDPDOP *ptr = opaque; virDomainObjPtr vm = ptr->vm; - if (reload_profile(ptr->drv, vm, file, true) < 0) { + if (reload_profile(ptr->mgr, vm, file, true) < 0) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot update AppArmor profile " @@ -371,7 +369,7 @@ AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, /* Called on libvirtd startup to see if AppArmor is available */ static int -AppArmorSecurityDriverProbe(void) +AppArmorSecurityManagerProbe(void) { char *template = NULL; int rc = SECURITY_DRIVER_DISABLE; @@ -403,21 +401,37 @@ AppArmorSecurityDriverProbe(void) * currently not used. */ static int -AppArmorSecurityDriverOpen(virSecurityDriverPtr drv, - bool allowDiskFormatProbing) +AppArmorSecurityManagerOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +AppArmorSecurityManagerClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) { - virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI); - virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing); return 0; } +static const char * +AppArmorSecurityManagerGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return SECURITY_APPARMOR_NAME; +} + +static const char * +AppArmorSecurityManagerGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return SECURITY_APPARMOR_VOID_DOI; +} + + /* Currently called in qemudStartVMDaemon to setup a 'label'. We look for and * use a profile based on the UUID, otherwise create one based on a template. * Keep in mind that this is called on 'start' with RestoreSecurityLabel being * called on shutdown. */ static int -AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm) { int rc = -1; @@ -472,7 +486,7 @@ AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, } static int -AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv, +AppArmorSetSecurityAllLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *stdin_path) { if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) @@ -480,7 +494,7 @@ AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv, /* if the profile is not already loaded, then load one */ if (profile_loaded(vm->def->seclabel.label) < 0) { - if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path, + if (load_profile(mgr, vm->def->seclabel.label, vm, stdin_path, false) < 0) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate AppArmor profile " @@ -496,7 +510,7 @@ AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv, * running. */ static int -AppArmorGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +AppArmorGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, virSecurityLabelPtr sec) { @@ -530,7 +544,7 @@ AppArmorGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, * more details. Currently called via qemudShutdownVMDaemon. */ static int -AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +AppArmorReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; @@ -544,7 +558,7 @@ AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, static int -AppArmorRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +AppArmorRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, int migrated ATTRIBUTE_UNUSED) { @@ -565,7 +579,7 @@ AppArmorRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, * LOCALSTATEDIR/log/libvirt/qemu/<vm name>.log */ static int -AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm) +AppArmorSetSecurityProcessLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; int rc = -1; @@ -574,12 +588,12 @@ AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm) if ((profile_name = get_profile_name(vm)) == NULL) return rc; - if (STRNEQ(drv->name, secdef->model)) { + if (STRNEQ(virSecurityManagerGetModel(mgr), secdef->model)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label driver mismatch: " "\'%s\' model configured for domain, but " "hypervisor driver is \'%s\'."), - secdef->model, drv->name); + secdef->model, virSecurityManagerGetModel(mgr)); if (use_apparmor() > 0) goto clean; } @@ -597,19 +611,33 @@ AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm) return rc; } +static int +AppArmorSetSecuritySocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +AppArmorClearSecuritySocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + /* Called when hotplugging */ static int -AppArmorRestoreSecurityImageLabel(virSecurityDriverPtr drv, +AppArmorRestoreSecurityImageLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainDiskDefPtr disk ATTRIBUTE_UNUSED) { - return reload_profile(drv, vm, NULL, false); + return reload_profile(mgr, vm, NULL, false); } /* Called when hotplugging */ static int -AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv, +AppArmorSetSecurityImageLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainDiskDefPtr disk) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; @@ -635,7 +663,7 @@ AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv, /* update the profile only if it is loaded */ if (profile_loaded(secdef->imagelabel) >= 0) { - if (load_profile(drv, secdef->imagelabel, vm, disk->src, + if (load_profile(mgr, secdef->imagelabel, vm, disk->src, false) < 0) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot update AppArmor profile " @@ -654,7 +682,8 @@ AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv, } static int -AppArmorSecurityVerify(virDomainDefPtr def) +AppArmorSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainDefPtr def) { const virSecurityLabelDefPtr secdef = &def->seclabel; @@ -670,7 +699,7 @@ AppArmorSecurityVerify(virDomainDefPtr def) } static int -AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +AppArmorReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm ATTRIBUTE_UNUSED) { /* NOOP. Nothing to reserve with AppArmor */ @@ -678,7 +707,7 @@ AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, } static int -AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv, +AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainHostdevDefPtr dev) @@ -698,7 +727,7 @@ AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv, if (VIR_ALLOC(ptr) < 0) return -1; - ptr->drv = drv; + ptr->mgr = mgr; ptr->vm = vm; switch (dev->source.subsys.type) { @@ -740,7 +769,7 @@ done: static int -AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv, +AppArmorRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED) @@ -749,42 +778,57 @@ AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv, if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) return 0; - return reload_profile(drv, vm, NULL, false); + return reload_profile(mgr, vm, NULL, false); } static int -AppArmorSetSavedStateLabel(virSecurityDriverPtr drv, +AppArmorSetSavedStateLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *savefile) { - return reload_profile(drv, vm, savefile, true); + return reload_profile(mgr, vm, savefile, true); } static int -AppArmorRestoreSavedStateLabel(virSecurityDriverPtr drv, +AppArmorRestoreSavedStateLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *savefile ATTRIBUTE_UNUSED) { - return reload_profile(drv, vm, NULL, false); + return reload_profile(mgr, vm, NULL, false); } virSecurityDriver virAppArmorSecurityDriver = { - .name = SECURITY_APPARMOR_NAME, - .probe = AppArmorSecurityDriverProbe, - .open = AppArmorSecurityDriverOpen, - .domainSecurityVerify = AppArmorSecurityVerify, - .domainSetSecurityImageLabel = AppArmorSetSecurityImageLabel, - .domainRestoreSecurityImageLabel = AppArmorRestoreSecurityImageLabel, - .domainGenSecurityLabel = AppArmorGenSecurityLabel, - .domainReserveSecurityLabel = AppArmorReserveSecurityLabel, - .domainReleaseSecurityLabel = AppArmorReleaseSecurityLabel, - .domainGetSecurityProcessLabel = AppArmorGetSecurityProcessLabel, - .domainSetSecurityProcessLabel = AppArmorSetSecurityProcessLabel, - .domainRestoreSecurityAllLabel = AppArmorRestoreSecurityAllLabel, - .domainSetSecurityAllLabel = AppArmorSetSecurityAllLabel, - .domainSetSecurityHostdevLabel = AppArmorSetSecurityHostdevLabel, - .domainRestoreSecurityHostdevLabel = AppArmorRestoreSecurityHostdevLabel, - .domainSetSavedStateLabel = AppArmorSetSavedStateLabel, - .domainRestoreSavedStateLabel = AppArmorRestoreSavedStateLabel, + 0, + SECURITY_APPARMOR_NAME, + AppArmorSecurityManagerProbe, + AppArmorSecurityManagerOpen, + AppArmorSecurityManagerClose, + + AppArmorSecurityManagerGetModel, + AppArmorSecurityManagerGetDOI, + + AppArmorSecurityVerify, + + AppArmorSetSecurityImageLabel, + AppArmorRestoreSecurityImageLabel, + + AppArmorSetSecuritySocketLabel, + AppArmorClearSecuritySocketLabel, + + AppArmorGenSecurityLabel, + AppArmorReserveSecurityLabel, + AppArmorReleaseSecurityLabel, + + AppArmorGetSecurityProcessLabel, + AppArmorSetSecurityProcessLabel, + + AppArmorSetSecurityAllLabel, + AppArmorRestoreSecurityAllLabel, + + AppArmorSetSecurityHostdevLabel, + AppArmorRestoreSecurityHostdevLabel, + + AppArmorSetSavedStateLabel, + AppArmorRestoreSavedStateLabel, }; diff --git a/src/security/security_apparmor.h b/src/security/security_apparmor.h index eb7e140..90d9ddb 100644 --- a/src/security/security_apparmor.h +++ b/src/security/security_apparmor.h @@ -14,6 +14,8 @@ #ifndef __VIR_SECURITY_APPARMOR_H__ # define __VIR_SECURITY_APPARMOR_H__ +#include "security_driver.h" + extern virSecurityDriver virAppArmorSecurityDriver; # define AA_PREFIX "libvirt-" diff --git a/src/security/security_dac.c b/src/security/security_dac.c new file mode 100644 index 0000000..edecaf9 --- /dev/null +++ b/src/security/security_dac.c @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * QEMU POSIX DAC security driver + */ +#include <config.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "security_dac.h" +#include "virterror_internal.h" +#include "util.h" +#include "memory.h" +#include "logging.h" +#include "pci.h" +#include "hostusb.h" +#include "storage_file.h" + +#define VIR_FROM_THIS VIR_FROM_SECURITY + +typedef struct _virSecurityDACData virSecurityDACData; +typedef virSecurityDACData *virSecurityDACDataPtr; + +struct _virSecurityDACData { + uid_t user; + gid_t group; + bool dynamicOwnership; +}; + +void virSecurityDACSetUser(virSecurityManagerPtr mgr, + uid_t user) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + priv->user = user; +} + +void virSecurityDACSetGroup(virSecurityManagerPtr mgr, + gid_t group) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + priv->group = group; +} + +void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr, + bool dynamicOwnership) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + priv->dynamicOwnership = dynamicOwnership; +} + +static virSecurityDriverStatus +virSecurityDACProbe(void) +{ + return SECURITY_DRIVER_ENABLE; +} + +static int +virSecurityDACOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityDACClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + + +static const char * virSecurityDACGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return "dac"; +} + +static const char * virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return "0"; +} + +static int +virSecurityDACSetOwnership(const char *path, int uid, int gid) +{ + VIR_INFO("Setting DAC user and group on '%s' to '%d:%d'", path, uid, gid); + + if (chown(path, uid, gid) < 0) { + struct stat sb; + int chown_errno = errno; + + if (stat(path, &sb) >= 0) { + if (sb.st_uid == uid && + sb.st_gid == gid) { + /* It's alright, there's nothing to change anyway. */ + return 0; + } + } + + if (chown_errno == EOPNOTSUPP) { + VIR_INFO("Setting user and group to '%d:%d' on '%s' not supported by filesystem", + uid, gid, path); + } else if (chown_errno == EPERM) { + VIR_INFO("Setting user and group to '%d:%d' on '%s' not permitted", + uid, gid, path); + } else if (chown_errno == EROFS) { + VIR_INFO("Setting user and group to '%d:%d' on '%s' not possible on readonly filesystem", + uid, gid, path); + } else { + virReportSystemError(chown_errno, + _("unable to set user and group to '%d:%d' on '%s'"), + uid, gid, path); + return -1; + } + } + return 0; +} + +static int +virSecurityDACRestoreSecurityFileLabel(const char *path) +{ + struct stat buf; + int rc = -1; + char *newpath = NULL; + + VIR_INFO("Restoring DAC user and group on '%s'", path); + + if (virFileResolveLink(path, &newpath) < 0) { + virReportSystemError(errno, + _("cannot resolve symlink %s"), path); + goto err; + } + + if (stat(newpath, &buf) != 0) + goto err; + + /* XXX record previous ownership */ + rc = virSecurityDACSetOwnership(newpath, 0, 0); + +err: + VIR_FREE(newpath); + return rc; +} + + +static int +virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, + const char *path, + size_t depth ATTRIBUTE_UNUSED, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + return virSecurityDACSetOwnership(path, priv->user, priv->group); +} + + +static int +virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk) + +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + if (!priv->dynamicOwnership) + return 0; + + return virDomainDiskDefForeachPath(disk, + virSecurityManagerGetAllowDiskFormatProbing(mgr), + false, + virSecurityDACSetSecurityFileLabel, + mgr); +} + + +static int +virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk, + int migrated) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + if (!priv->dynamicOwnership) + return 0; + + /* Don't restore labels on readoly/shared disks, because + * other VMs may still be accessing these + * Alternatively we could iterate over all running + * domains and try to figure out if it is in use, but + * this would not work for clustered filesystems, since + * we can't see running VMs using the file on other nodes + * Safest bet is thus to skip the restore step. + */ + if (disk->readonly || disk->shared) + return 0; + + if (!disk->src) + return 0; + + /* If we have a shared FS & doing migrated, we must not + * change ownership, because that kills access on the + * destination host which is sub-optimal for the guest + * VM's I/O attempts :-) + */ + if (migrated) { + int rc = virStorageFileIsSharedFS(disk->src); + if (rc < 0) + return -1; + if (rc == 1) { + VIR_DEBUG("Skipping image label restore on %s because FS is shared", + disk->src); + return 0; + } + } + + return virSecurityDACRestoreSecurityFileLabel(disk->src); +} + + +static int +virSecurityDACRestoreSecurityImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk) +{ + return virSecurityDACRestoreSecurityImageLabelInt(mgr, vm, disk, 0); +} + + +static int +virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + return virSecurityDACSetOwnership(file, priv->user, priv->group); +} + + +static int +virSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + return virSecurityDACSetOwnership(file, priv->user, priv->group); +} + + +static int +virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int ret = -1; + + if (!priv->dynamicOwnership) + return 0; + + if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + return 0; + + switch (dev->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { + usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus, + dev->source.subsys.u.usb.device); + + if (!usb) + goto done; + + ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr); + usbFreeDevice(usb); + break; + } + + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: { + pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain, + dev->source.subsys.u.pci.bus, + dev->source.subsys.u.pci.slot, + dev->source.subsys.u.pci.function); + + if (!pci) + goto done; + + ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr); + pciFreeDevice(pci); + + break; + } + + default: + ret = 0; + break; + } + +done: + return ret; +} + + +static int +virSecurityDACRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque ATTRIBUTE_UNUSED) +{ + return virSecurityDACRestoreSecurityFileLabel(file); +} + + +static int +virSecurityDACRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque ATTRIBUTE_UNUSED) +{ + return virSecurityDACRestoreSecurityFileLabel(file); +} + + +static int +virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev) + +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int ret = -1; + + if (!priv->dynamicOwnership) + return 0; + + if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + return 0; + + switch (dev->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { + usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus, + dev->source.subsys.u.usb.device); + + if (!usb) + goto done; + + ret = usbDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr); + usbFreeDevice(usb); + + break; + } + + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: { + pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain, + dev->source.subsys.u.pci.bus, + dev->source.subsys.u.pci.slot, + dev->source.subsys.u.pci.function); + + if (!pci) + goto done; + + ret = pciDeviceFileIterate(pci, virSecurityDACRestoreSecurityPCILabel, mgr); + pciFreeDevice(pci); + + break; + } + + default: + ret = 0; + break; + } + +done: + return ret; +} + + +static int +virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr, + virDomainChrDefPtr dev) + +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + char *in = NULL, *out = NULL; + int ret = -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); + break; + + case VIR_DOMAIN_CHR_TYPE_PIPE: + if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) || + (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) { + virReportOOMError(); + goto done; + } + if ((virSecurityDACSetOwnership(in, priv->user, priv->group) < 0) || + (virSecurityDACSetOwnership(out, priv->user, priv->group) < 0)) + goto done; + ret = 0; + break; + + default: + ret = 0; + break; + } + +done: + VIR_FREE(in); + VIR_FREE(out); + return ret; +} + +static int +virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainChrDefPtr dev) +{ + char *in = NULL, *out = NULL; + int ret = -1; + + switch (dev->type) { + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: + ret = virSecurityDACRestoreSecurityFileLabel(dev->data.file.path); + break; + + case VIR_DOMAIN_CHR_TYPE_PIPE: + if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) || + (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) { + virReportOOMError(); + goto done; + } + if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) || + (virSecurityDACRestoreSecurityFileLabel(in) < 0)) + goto done; + ret = 0; + break; + + default: + ret = 0; + break; + } + +done: + VIR_FREE(in); + VIR_FREE(out); + return ret; +} + + +static int +virSecurityDACRestoreChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainChrDefPtr dev, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + + return virSecurityDACRestoreChardevLabel(mgr, dev); +} + + +static int +virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + int migrated) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int i; + int rc = 0; + + if (!priv->dynamicOwnership) + return 0; + + + VIR_DEBUG("Restoring security label on %s migrated=%d", + vm->def->name, migrated); + + for (i = 0 ; i < vm->def->nhostdevs ; i++) { + if (virSecurityDACRestoreSecurityHostdevLabel(mgr, + vm, + vm->def->hostdevs[i]) < 0) + rc = -1; + } + for (i = 0 ; i < vm->def->ndisks ; i++) { + if (virSecurityDACRestoreSecurityImageLabelInt(mgr, + vm, + vm->def->disks[i], + migrated) < 0) + rc = -1; + } + + if (virDomainChrDefForeach(vm->def, + false, + virSecurityDACRestoreChardevCallback, + vm) < 0) + rc = -1; + + if (vm->def->os.kernel && + virSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0) + rc = -1; + + if (vm->def->os.initrd && + virSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainChrDefPtr dev, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + + return virSecurityDACSetChardevLabel(mgr, dev); +} + + +static int +virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *stdin_path ATTRIBUTE_UNUSED) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int i; + + if (!priv->dynamicOwnership) + return 0; + + for (i = 0 ; i < vm->def->ndisks ; i++) { + /* XXX fixme - we need to recursively label the entriy tree :-( */ + if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) + continue; + if (virSecurityDACSetSecurityImageLabel(mgr, + vm, + vm->def->disks[i]) < 0) + return -1; + } + for (i = 0 ; i < vm->def->nhostdevs ; i++) { + if (virSecurityDACSetSecurityHostdevLabel(mgr, + vm, + vm->def->hostdevs[i]) < 0) + return -1; + } + + if (virDomainChrDefForeach(vm->def, + true, + virSecurityDACSetChardevCallback, + vm) < 0) + return -1; + + if (vm->def->os.kernel && + virSecurityDACSetOwnership(vm->def->os.kernel, + priv->user, + priv->group) < 0) + return -1; + + if (vm->def->os.initrd && + virSecurityDACSetOwnership(vm->def->os.initrd, + priv->user, + priv->group) < 0) + return -1; + + return 0; +} + + +static int +virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *savefile) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + return virSecurityDACSetOwnership(savefile, priv->user, priv->group); +} + + +static int +virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *savefile) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + if (!priv->dynamicOwnership) + return 0; + + return virSecurityDACRestoreSecurityFileLabel(savefile); +} + + +static int +virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + DEBUG("Dropping privileges of VM to %d:%d", priv->user, priv->group); + + if (virSetUIDGID(priv->user, priv->group) < 0) + return -1; + + return 0; +} + + +static int +virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainDefPtr def ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityDACGenLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virSecurityLabelPtr seclabel ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityDACSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + + +static int +virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + + +virSecurityDriver virSecurityDriverDAC = { + sizeof(virSecurityDACData), + "virDAC", + + virSecurityDACProbe, + virSecurityDACOpen, + virSecurityDACClose, + + virSecurityDACGetModel, + virSecurityDACGetDOI, + + virSecurityDACVerify, + + virSecurityDACSetSecurityImageLabel, + virSecurityDACRestoreSecurityImageLabel, + + virSecurityDACSetSocketLabel, + virSecurityDACClearSocketLabel, + + virSecurityDACGenLabel, + virSecurityDACReserveLabel, + virSecurityDACReleaseLabel, + + virSecurityDACGetProcessLabel, + virSecurityDACSetProcessLabel, + + virSecurityDACSetSecurityAllLabel, + virSecurityDACRestoreSecurityAllLabel, + + virSecurityDACSetSecurityHostdevLabel, + virSecurityDACRestoreSecurityHostdevLabel, + + virSecurityDACSetSavedStateLabel, + virSecurityDACRestoreSavedStateLabel, +}; diff --git a/src/security/security_dac.h b/src/security/security_dac.h new file mode 100644 index 0000000..b690236 --- /dev/null +++ b/src/security/security_dac.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * POSIX DAC security driver + */ + +#include "security_driver.h" + +#ifndef __VIR_SECURITY_DAC +# define __VIR_SECURITY_DAC + +extern virSecurityDriver virSecurityDriverDAC; + +void virSecurityDACSetUser(virSecurityManagerPtr mgr, + uid_t user); +void virSecurityDACSetGroup(virSecurityManagerPtr mgr, + gid_t group); + +void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr, + bool dynamic); + +#endif /* __VIR_SECURITY_DAC */ diff --git a/src/security/security_driver.c b/src/security/security_driver.c index 9e32fa4..6d75dcc 100644 --- a/src/security/security_driver.c +++ b/src/security/security_driver.c @@ -24,116 +24,52 @@ # include "security_apparmor.h" #endif +#include "security_nop.h" + static virSecurityDriverPtr security_drivers[] = { #ifdef WITH_SECDRIVER_SELINUX - &virSELinuxSecurityDriver, + &virSecurityDriverSELinux, #endif #ifdef WITH_SECDRIVER_APPARMOR &virAppArmorSecurityDriver, #endif - NULL + &virSecurityDriverNop, /* Must always be last, since it will always probe */ }; -int -virSecurityDriverVerify(virDomainDefPtr def) -{ - unsigned int i; - const virSecurityLabelDefPtr secdef = &def->seclabel; - - if (!secdef->model || - STREQ(secdef->model, "none")) - return 0; - - for (i = 0; security_drivers[i] != NULL ; i++) { - if (STREQ(security_drivers[i]->name, secdef->model)) { - return security_drivers[i]->domainSecurityVerify(def); - } - } - virSecurityReportError(VIR_ERR_XML_ERROR, - _("invalid security model '%s'"), secdef->model); - return -1; -} - -int -virSecurityDriverStartup(virSecurityDriverPtr *drv, - const char *name, - bool allowDiskFormatProbing) +virSecurityDriverPtr virSecurityDriverLookup(const char *name) { - unsigned int i; - - if (name && STREQ(name, "none")) - return -2; + virSecurityDriverPtr drv = NULL; + int i; - for (i = 0; security_drivers[i] != NULL ; i++) { + for (i = 0; i < ARRAY_CARDINALITY(security_drivers) ; i++) { virSecurityDriverPtr tmp = security_drivers[i]; - if (name && STRNEQ(tmp->name, name)) - continue; - - switch (tmp->probe()) { - case SECURITY_DRIVER_ENABLE: - virSecurityDriverInit(tmp); - if (tmp->open(tmp, allowDiskFormatProbing) == -1) { - return -1; - } else { - *drv = tmp; - return 0; + if (name) { + if (STREQ(tmp->name, name)) { + drv = tmp; + break; } - break; + } else { + switch (tmp->probe()) { + case SECURITY_DRIVER_ENABLE: + drv = tmp; + break; - case SECURITY_DRIVER_DISABLE: - break; + case SECURITY_DRIVER_DISABLE: + break; - default: - return -1; + default: + return NULL; + } } } - return -2; -} - -/* - * Helpers - */ -void -virSecurityDriverInit(virSecurityDriverPtr drv) -{ - memset(&drv->_private, 0, sizeof drv->_private); -} -int -virSecurityDriverSetDOI(virSecurityDriverPtr drv, - const char *doi) -{ - if (strlen(doi) >= VIR_SECURITY_DOI_BUFLEN) { + if (!drv) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, - _("%s: DOI \'%s\' is " - "longer than the maximum allowed length of %d"), - __func__, doi, VIR_SECURITY_DOI_BUFLEN - 1); - return -1; + "Security driver %s not found", NULLSTR(name)); + return NULL; } - strcpy(drv->_private.doi, doi); - return 0; -} - -const char * -virSecurityDriverGetDOI(virSecurityDriverPtr drv) -{ - return drv->_private.doi; -} -const char * -virSecurityDriverGetModel(virSecurityDriverPtr drv) -{ - return drv->name; + return drv; } -void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv, - bool allowDiskFormatProbing) -{ - drv->_private.allowDiskFormatProbing = allowDiskFormatProbing; -} - -bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv) -{ - return drv->_private.allowDiskFormatProbing; -} diff --git a/src/security/security_driver.h b/src/security/security_driver.h index d768f32..e5a8d41 100644 --- a/src/security/security_driver.h +++ b/src/security/security_driver.h @@ -16,6 +16,8 @@ # include "internal.h" # include "domain_conf.h" +# include "security_manager.h" + /* * Return values for security driver probing: the driver will determine * whether it should be enabled or disabled. @@ -29,104 +31,91 @@ typedef enum { typedef struct _virSecurityDriver virSecurityDriver; typedef virSecurityDriver *virSecurityDriverPtr; -typedef struct _virSecurityDriverState virSecurityDriverState; -typedef virSecurityDriverState *virSecurityDriverStatePtr; - typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void); -typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv, - bool allowDiskFormatProbing); -typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDriverOpen) (virSecurityManagerPtr mgr); +typedef int (*virSecurityDriverClose) (virSecurityManagerPtr mgr); + +typedef const char *(*virSecurityDriverGetModel) (virSecurityManagerPtr mgr); +typedef const char *(*virSecurityDriverGetDOI) (virSecurityManagerPtr mgr); + +typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainDiskDefPtr disk); -typedef int (*virSecurityDomainSetSocketLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainSetSocketLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm); -typedef int (*virSecurityDomainClearSocketLabel)(virSecurityDriverPtr drv, +typedef int (*virSecurityDomainClearSocketLabel)(virSecurityManagerPtr mgr, virDomainObjPtr vm); -typedef int (*virSecurityDomainSetImageLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainSetImageLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainDiskDefPtr disk); -typedef int (*virSecurityDomainRestoreHostdevLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainRestoreHostdevLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainHostdevDefPtr dev); -typedef int (*virSecurityDomainSetHostdevLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainSetHostdevLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainHostdevDefPtr dev); -typedef int (*virSecurityDomainSetSavedStateLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainSetSavedStateLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *savefile); -typedef int (*virSecurityDomainRestoreSavedStateLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainRestoreSavedStateLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *savefile); -typedef int (*virSecurityDomainGenLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainGenLabel) (virSecurityManagerPtr mgr, virDomainObjPtr sec); -typedef int (*virSecurityDomainReserveLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainReserveLabel) (virSecurityManagerPtr mgr, virDomainObjPtr sec); -typedef int (*virSecurityDomainReleaseLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainReleaseLabel) (virSecurityManagerPtr mgr, virDomainObjPtr sec); -typedef int (*virSecurityDomainSetAllLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainSetAllLabel) (virSecurityManagerPtr mgr, virDomainObjPtr sec, const char *stdin_path); -typedef int (*virSecurityDomainRestoreAllLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainRestoreAllLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, int migrated); -typedef int (*virSecurityDomainGetProcessLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainGetProcessLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm, virSecurityLabelPtr sec); -typedef int (*virSecurityDomainSetProcessLabel) (virSecurityDriverPtr drv, +typedef int (*virSecurityDomainSetProcessLabel) (virSecurityManagerPtr mgr, virDomainObjPtr vm); -typedef int (*virSecurityDomainSecurityVerify) (virDomainDefPtr def); +typedef int (*virSecurityDomainSecurityVerify) (virSecurityManagerPtr mgr, + virDomainDefPtr def); + struct _virSecurityDriver { + size_t privateDataLen; const char *name; virSecurityDriverProbe probe; virSecurityDriverOpen open; + virSecurityDriverClose close; + + virSecurityDriverGetModel getModel; + virSecurityDriverGetDOI getDOI; + virSecurityDomainSecurityVerify domainSecurityVerify; + + virSecurityDomainSetImageLabel domainSetSecurityImageLabel; virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel; + virSecurityDomainSetSocketLabel domainSetSecuritySocketLabel; virSecurityDomainClearSocketLabel domainClearSecuritySocketLabel; - virSecurityDomainSetImageLabel domainSetSecurityImageLabel; + virSecurityDomainGenLabel domainGenSecurityLabel; virSecurityDomainReserveLabel domainReserveSecurityLabel; virSecurityDomainReleaseLabel domainReleaseSecurityLabel; + virSecurityDomainGetProcessLabel domainGetSecurityProcessLabel; virSecurityDomainSetProcessLabel domainSetSecurityProcessLabel; + virSecurityDomainSetAllLabel domainSetSecurityAllLabel; virSecurityDomainRestoreAllLabel domainRestoreSecurityAllLabel; - virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel; + virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel; + virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel; + virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel; virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel; - - /* - * This is internally managed driver state and should only be accessed - * via helpers below. - */ - struct { - char doi[VIR_SECURITY_DOI_BUFLEN]; - bool allowDiskFormatProbing; - } _private; }; -/* Global methods */ -int virSecurityDriverStartup(virSecurityDriverPtr *drv, - const char *name, - bool allowDiskFormatProbing); - -int -virSecurityDriverVerify(virDomainDefPtr def); - -# define virSecurityReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) - -/* Helpers */ -void virSecurityDriverInit(virSecurityDriverPtr drv); -int virSecurityDriverSetDOI(virSecurityDriverPtr drv, - const char *doi); -void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv, - bool allowDiskFormatProbing); -const char *virSecurityDriverGetDOI(virSecurityDriverPtr drv); -const char *virSecurityDriverGetModel(virSecurityDriverPtr drv); -bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv); +virSecurityDriverPtr virSecurityDriverLookup(const char *name); #endif /* __VIR_SECURITY_H__ */ diff --git a/src/security/security_manager.c b/src/security/security_manager.c new file mode 100644 index 0000000..7ab6e37 --- /dev/null +++ b/src/security/security_manager.c @@ -0,0 +1,291 @@ + +#include <config.h> + + +#include "security_driver.h" +#include "security_stack.h" +#include "security_dac.h" +#include "virterror_internal.h" +#include "memory.h" +#include "logging.h" + +#define VIR_FROM_THIS VIR_FROM_SECURITY + + +struct _virSecurityManager { + virSecurityDriverPtr drv; + bool allowDiskFormatProbing; +}; + +static virSecurityManagerPtr virSecurityManagerNewDriver(virSecurityDriverPtr drv, + bool allowDiskFormatProbing) +{ + virSecurityManagerPtr mgr; + + if (VIR_ALLOC_VAR(mgr, char, drv->privateDataLen) < 0) { + virReportOOMError(); + return NULL; + } + + mgr->drv = drv; + mgr->allowDiskFormatProbing = allowDiskFormatProbing; + + if (drv->open(mgr) < 0) { + virSecurityManagerFree(mgr); + return NULL; + } + + return mgr; +} + +virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary, + virSecurityManagerPtr secondary) +{ + virSecurityManagerPtr mgr = + virSecurityManagerNewDriver(&virSecurityDriverStack, + virSecurityManagerGetAllowDiskFormatProbing(primary)); + + virSecurityStackSetPrimary(mgr, primary); + virSecurityStackSetSecondary(mgr, secondary); + + return mgr; +} + +virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user, + gid_t group, + bool allowDiskFormatProbing, + bool dynamicOwnership) +{ + virSecurityManagerPtr mgr = + virSecurityManagerNewDriver(&virSecurityDriverDAC, + allowDiskFormatProbing); + + virSecurityDACSetUser(mgr, user); + virSecurityDACSetGroup(mgr, group); + virSecurityDACSetDynamicOwnership(mgr, dynamicOwnership); + + return mgr; +} + +virSecurityManagerPtr virSecurityManagerNew(const char *name, + bool allowDiskFormatProbing) +{ + virSecurityDriverPtr drv = virSecurityDriverLookup(name); + if (!drv) + return NULL; + + return virSecurityManagerNewDriver(drv, allowDiskFormatProbing); +} + + +void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr) +{ + return mgr + sizeof(mgr); +} + + +void virSecurityManagerFree(virSecurityManagerPtr mgr) +{ + if (!mgr) + return; + + if (mgr->drv->close) + mgr->drv->close(mgr); + + VIR_FREE(mgr); +} + +const char * +virSecurityManagerGetDOI(virSecurityManagerPtr mgr) +{ + if (mgr->drv->getDOI) + return mgr->drv->getDOI(mgr); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; +} + +const char * +virSecurityManagerGetModel(virSecurityManagerPtr mgr) +{ + if (mgr->drv->getModel) + return mgr->drv->getModel(mgr); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; +} + +bool virSecurityManagerGetAllowDiskFormatProbing(virSecurityManagerPtr mgr) +{ + return mgr->allowDiskFormatProbing; +} + +int virSecurityManagerRestoreImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk) +{ + if (mgr->drv->domainRestoreSecurityImageLabel) + return mgr->drv->domainRestoreSecurityImageLabel(mgr, vm, disk); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerSetSocketLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + if (mgr->drv->domainSetSecuritySocketLabel) + return mgr->drv->domainSetSecuritySocketLabel(mgr, vm); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerClearSocketLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + if (mgr->drv->domainClearSecuritySocketLabel) + return mgr->drv->domainClearSecuritySocketLabel(mgr, vm); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerSetImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk) +{ + if (mgr->drv->domainSetSecurityImageLabel) + return mgr->drv->domainSetSecurityImageLabel(mgr, vm, disk); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerRestoreHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev) +{ + if (mgr->drv->domainRestoreSecurityHostdevLabel) + return mgr->drv->domainRestoreSecurityHostdevLabel(mgr, vm, dev); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerSetHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev) +{ + if (mgr->drv->domainSetSecurityHostdevLabel) + return mgr->drv->domainSetSecurityHostdevLabel(mgr, vm, dev); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerSetSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *savefile) +{ + if (mgr->drv->domainSetSavedStateLabel) + return mgr->drv->domainSetSavedStateLabel(mgr, vm, savefile); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerRestoreSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *savefile) +{ + if (mgr->drv->domainRestoreSavedStateLabel) + return mgr->drv->domainRestoreSavedStateLabel(mgr, vm, savefile); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerGenLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + if (mgr->drv->domainGenSecurityLabel) + return mgr->drv->domainGenSecurityLabel(mgr, vm); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + if (mgr->drv->domainReserveSecurityLabel) + return mgr->drv->domainReserveSecurityLabel(mgr, vm); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + if (mgr->drv->domainReleaseSecurityLabel) + return mgr->drv->domainReleaseSecurityLabel(mgr, vm); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerSetAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *stdin_path) +{ + if (mgr->drv->domainSetSecurityAllLabel) + return mgr->drv->domainSetSecurityAllLabel(mgr, vm, stdin_path); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerRestoreAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + int migrated) +{ + if (mgr->drv->domainRestoreSecurityAllLabel) + return mgr->drv->domainRestoreSecurityAllLabel(mgr, vm, migrated); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerGetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virSecurityLabelPtr sec) +{ + if (mgr->drv->domainGetSecurityProcessLabel) + return mgr->drv->domainGetSecurityProcessLabel(mgr, vm, sec); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + if (mgr->drv->domainSetSecurityProcessLabel) + return mgr->drv->domainSetSecurityProcessLabel(mgr, vm); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +int virSecurityManagerVerify(virSecurityManagerPtr mgr, + virDomainDefPtr def) +{ + if (mgr->drv->domainSecurityVerify) + return mgr->drv->domainSecurityVerify(mgr, def); + + virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + diff --git a/src/security/security_manager.h b/src/security/security_manager.h new file mode 100644 index 0000000..c0ef84f --- /dev/null +++ b/src/security/security_manager.h @@ -0,0 +1,74 @@ + +#ifndef VIR_SECURITY_MANAGER_H__ +#define VIR_SECURITY_MANAGER_H__ + +# define virSecurityReportError(code, ...) \ + virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + + +typedef struct _virSecurityManager virSecurityManager; +typedef virSecurityManager *virSecurityManagerPtr; + +virSecurityManagerPtr virSecurityManagerNew(const char *name, + bool allowDiskFormatProbing); + +virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary, + virSecurityManagerPtr secondary); + +virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user, + gid_t group, + bool allowDiskFormatProbing, + bool dynamicOwnership); + +void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr); + +void virSecurityManagerFree(virSecurityManagerPtr mgr); + +const char *virSecurityManagerGetDOI(virSecurityManagerPtr mgr); +const char *virSecurityManagerGetModel(virSecurityManagerPtr mgr); +bool virSecurityManagerGetAllowDiskFormatProbing(virSecurityManagerPtr mgr); + +int virSecurityManagerRestoreImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk); +int virSecurityManagerSetSocketLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm); +int virSecurityManagerClearSocketLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm); +int virSecurityManagerSetImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk); +int virSecurityManagerRestoreHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev); +int virSecurityManagerSetHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev); +int virSecurityManagerSetSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *savefile); +int virSecurityManagerRestoreSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *savefile); +int virSecurityManagerGenLabel(virSecurityManagerPtr mgr, + virDomainObjPtr sec); +int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr, + virDomainObjPtr sec); +int virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr, + virDomainObjPtr sec); +int virSecurityManagerSetAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr sec, + const char *stdin_path); +int virSecurityManagerRestoreAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + int migrated); +int virSecurityManagerGetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virSecurityLabelPtr sec); +int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm); +int virSecurityManagerVerify(virSecurityManagerPtr mgr, + virDomainDefPtr def); + +#endif /* VIR_SECURITY_MANAGER_H__ */ diff --git a/src/security/security_nop.c b/src/security/security_nop.c new file mode 100644 index 0000000..947cf55 --- /dev/null +++ b/src/security/security_nop.c @@ -0,0 +1,168 @@ + + +#include <config.h> + +#include "security_nop.h" + +static virSecurityDriverStatus virSecurityDriverProbeNop(void) +{ + return SECURITY_DRIVER_ENABLE; +} + +static int virSecurityDriverOpenNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDriverCloseNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + +static const char * virSecurityDriverGetModelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return "none"; +} + +static const char * virSecurityDriverGetDOINop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return "0"; +} + +static int virSecurityDomainRestoreImageLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainSetSocketLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainClearSocketLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainSetImageLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainRestoreHostdevLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainSetHostdevLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainSetSavedStateLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *savefile ATTRIBUTE_UNUSED) +{ + return 0; +} +static int virSecurityDomainRestoreSavedStateLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *savefile ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainGenLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr sec ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainReserveLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr sec ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainReleaseLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr sec ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainSetAllLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr sec ATTRIBUTE_UNUSED, + const char *stdin_path ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainRestoreAllLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + int migrated ATTRIBUTE_UNUSED) +{ + return 0; +} +static int virSecurityDomainGetProcessLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virSecurityLabelPtr sec ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainSetProcessLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int virSecurityDomainVerifyNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainDefPtr def ATTRIBUTE_UNUSED) +{ + return 0; +} + +virSecurityDriver virSecurityDriverNop = { + 0, + "nop", + virSecurityDriverProbeNop, + virSecurityDriverOpenNop, + virSecurityDriverCloseNop, + + virSecurityDriverGetModelNop, + virSecurityDriverGetDOINop, + + virSecurityDomainVerifyNop, + + virSecurityDomainSetImageLabelNop, + virSecurityDomainRestoreImageLabelNop, + + virSecurityDomainSetSocketLabelNop, + virSecurityDomainClearSocketLabelNop, + + virSecurityDomainGenLabelNop, + virSecurityDomainReserveLabelNop, + virSecurityDomainReleaseLabelNop, + + virSecurityDomainGetProcessLabelNop, + virSecurityDomainSetProcessLabelNop, + + virSecurityDomainSetAllLabelNop, + virSecurityDomainRestoreAllLabelNop, + + virSecurityDomainSetHostdevLabelNop, + virSecurityDomainRestoreHostdevLabelNop, + + virSecurityDomainSetSavedStateLabelNop, + virSecurityDomainRestoreSavedStateLabelNop, +}; diff --git a/src/security/security_nop.h b/src/security/security_nop.h new file mode 100644 index 0000000..714e646 --- /dev/null +++ b/src/security/security_nop.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ +#ifndef __VIR_SECURITY_NOP_H__ +# define __VIR_SECURITY_NOP_H__ + +#include "security_driver.h" + +extern virSecurityDriver virSecurityDriverNop; + +#endif /* __VIR_SECURITY_NOP_H__ */ diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 47da677..d06afde 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -160,7 +160,7 @@ SELinuxInitialize(void) } static int -SELinuxGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm) { int rc = -1; @@ -225,7 +225,7 @@ done: } static int -SELinuxReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm) { security_context_t pctx; @@ -270,20 +270,34 @@ SELinuxSecurityDriverProbe(void) } static int -SELinuxSecurityDriverOpen(virSecurityDriverPtr drv, - bool allowDiskFormatProbing) +SELinuxSecurityDriverOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return SELinuxInitialize(); +} + +static int +SELinuxSecurityDriverClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + + +static const char *SELinuxSecurityGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return SECURITY_SELINUX_NAME; +} + +static const char *SELinuxSecurityGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) { /* * Where will the DOI come from? SELinux configuration, or qemu * configuration? For the moment, we'll just set it to "0". */ - virSecurityDriverSetDOI(drv, SECURITY_SELINUX_VOID_DOI); - virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing); - return SELinuxInitialize(); + return SECURITY_SELINUX_VOID_DOI; } static int -SELinuxGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, virSecurityLabelPtr sec) { @@ -415,7 +429,7 @@ err: } static int -SELinuxRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, virDomainDiskDefPtr disk, int migrated) @@ -460,11 +474,11 @@ SELinuxRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, static int -SELinuxRestoreSecurityImageLabel(virSecurityDriverPtr drv, +SELinuxRestoreSecurityImageLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainDiskDefPtr disk) { - return SELinuxRestoreSecurityImageLabelInt(drv, vm, disk, 0); + return SELinuxRestoreSecurityImageLabelInt(mgr, vm, disk, 0); } @@ -498,13 +512,13 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk, } static int -SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv, +SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, virDomainDiskDefPtr disk) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; - bool allowDiskFormatProbing = virSecurityDriverGetAllowDiskFormatProbing(drv); + bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr); if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) return 0; @@ -538,7 +552,7 @@ SELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, } static int -SELinuxSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, virDomainHostdevDefPtr dev) @@ -607,7 +621,7 @@ SELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, } static int -SELinuxRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, virDomainHostdevDefPtr dev) @@ -756,7 +770,7 @@ SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, static int -SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, int migrated ATTRIBUTE_UNUSED) { @@ -770,13 +784,13 @@ SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, return 0; for (i = 0 ; i < vm->def->nhostdevs ; i++) { - if (SELinuxRestoreSecurityHostdevLabel(drv, + if (SELinuxRestoreSecurityHostdevLabel(mgr, vm, vm->def->hostdevs[i]) < 0) rc = -1; } for (i = 0 ; i < vm->def->ndisks ; i++) { - if (SELinuxRestoreSecurityImageLabelInt(drv, + if (SELinuxRestoreSecurityImageLabelInt(mgr, vm, vm->def->disks[i], migrated) < 0) @@ -801,7 +815,7 @@ SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, } static int -SELinuxReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm) { const virSecurityLabelDefPtr secdef = &vm->def->seclabel; @@ -825,7 +839,7 @@ SELinuxReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, static int -SELinuxSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, const char *savefile) { @@ -839,7 +853,7 @@ SELinuxSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, static int -SELinuxRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, +SELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, const char *savefile) { @@ -853,9 +867,19 @@ SELinuxRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, static int -SELinuxSecurityVerify(virDomainDefPtr def) +SELinuxSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainDefPtr def) { const virSecurityLabelDefPtr secdef = &def->seclabel; + if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + _("security label driver mismatch: " + "'%s' model configured for domain, but " + "hypervisor driver is '%s'."), + secdef->model, virSecurityManagerGetModel(mgr)); + return -1; + } + if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) { if (security_check_context(secdef->label) != 0) { virSecurityReportError(VIR_ERR_XML_ERROR, @@ -867,7 +891,7 @@ SELinuxSecurityVerify(virDomainDefPtr def) } static int -SELinuxSetSecurityProcessLabel(virSecurityDriverPtr drv, +SELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm) { /* TODO: verify DOI */ @@ -876,12 +900,12 @@ SELinuxSetSecurityProcessLabel(virSecurityDriverPtr drv, if (vm->def->seclabel.label == NULL) return 0; - if (!STREQ(drv->name, secdef->model)) { + if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label driver mismatch: " "'%s' model configured for domain, but " "hypervisor driver is '%s'."), - secdef->model, drv->name); + secdef->model, virSecurityManagerGetModel(mgr)); if (security_getenforce() == 1) return -1; } @@ -898,7 +922,7 @@ SELinuxSetSecurityProcessLabel(virSecurityDriverPtr drv, } static int -SELinuxSetSecuritySocketLabel(virSecurityDriverPtr drv, +SELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm) { /* TODO: verify DOI */ @@ -911,12 +935,12 @@ SELinuxSetSecuritySocketLabel(virSecurityDriverPtr drv, if (vm->def->seclabel.label == NULL) return 0; - if (!STREQ(drv->name, secdef->model)) { + if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label driver mismatch: " "'%s' model configured for domain, but " "hypervisor driver is '%s'."), - secdef->model, drv->name); + secdef->model, virSecurityManagerGetModel(mgr)); goto done; } @@ -969,7 +993,7 @@ done: } static int -SELinuxClearSecuritySocketLabel(virSecurityDriverPtr drv, +SELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm) { /* TODO: verify DOI */ @@ -978,12 +1002,12 @@ SELinuxClearSecuritySocketLabel(virSecurityDriverPtr drv, if (vm->def->seclabel.label == NULL) return 0; - if (!STREQ(drv->name, secdef->model)) { + if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label driver mismatch: " "'%s' model configured for domain, but " "hypervisor driver is '%s'."), - secdef->model, drv->name); + secdef->model, virSecurityManagerGetModel(mgr)); if (security_getenforce() == 1) return -1; } @@ -1011,7 +1035,7 @@ SELinuxSetSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, static int -SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv, +SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm, const char *stdin_path) { @@ -1028,12 +1052,12 @@ SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv, vm->def->disks[i]->src, vm->def->disks[i]->dst); continue; } - if (SELinuxSetSecurityImageLabel(drv, + if (SELinuxSetSecurityImageLabel(mgr, vm, vm->def->disks[i]) < 0) return -1; } for (i = 0 ; i < vm->def->nhostdevs ; i++) { - if (SELinuxSetSecurityHostdevLabel(drv, + if (SELinuxSetSecurityHostdevLabel(mgr, vm, vm->def->hostdevs[i]) < 0) return -1; @@ -1063,24 +1087,37 @@ SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv, return 0; } -virSecurityDriver virSELinuxSecurityDriver = { - .name = SECURITY_SELINUX_NAME, - .probe = SELinuxSecurityDriverProbe, - .open = SELinuxSecurityDriverOpen, - .domainSecurityVerify = SELinuxSecurityVerify, - .domainSetSecurityImageLabel = SELinuxSetSecurityImageLabel, - .domainSetSecuritySocketLabel = SELinuxSetSecuritySocketLabel, - .domainClearSecuritySocketLabel = SELinuxClearSecuritySocketLabel, - .domainRestoreSecurityImageLabel = SELinuxRestoreSecurityImageLabel, - .domainGenSecurityLabel = SELinuxGenSecurityLabel, - .domainReserveSecurityLabel = SELinuxReserveSecurityLabel, - .domainReleaseSecurityLabel = SELinuxReleaseSecurityLabel, - .domainGetSecurityProcessLabel = SELinuxGetSecurityProcessLabel, - .domainSetSecurityProcessLabel = SELinuxSetSecurityProcessLabel, - .domainRestoreSecurityAllLabel = SELinuxRestoreSecurityAllLabel, - .domainSetSecurityAllLabel = SELinuxSetSecurityAllLabel, - .domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel, - .domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel, - .domainSetSavedStateLabel = SELinuxSetSavedStateLabel, - .domainRestoreSavedStateLabel = SELinuxRestoreSavedStateLabel, +virSecurityDriver virSecurityDriverSELinux = { + 0, + SECURITY_SELINUX_NAME, + SELinuxSecurityDriverProbe, + SELinuxSecurityDriverOpen, + SELinuxSecurityDriverClose, + + SELinuxSecurityGetModel, + SELinuxSecurityGetDOI, + + SELinuxSecurityVerify, + + SELinuxSetSecurityImageLabel, + SELinuxRestoreSecurityImageLabel, + + SELinuxSetSecuritySocketLabel, + SELinuxClearSecuritySocketLabel, + + SELinuxGenSecurityLabel, + SELinuxReserveSecurityLabel, + SELinuxReleaseSecurityLabel, + + SELinuxGetSecurityProcessLabel, + SELinuxSetSecurityProcessLabel, + + SELinuxSetSecurityAllLabel, + SELinuxRestoreSecurityAllLabel, + + SELinuxSetSecurityHostdevLabel, + SELinuxRestoreSecurityHostdevLabel, + + SELinuxSetSavedStateLabel, + SELinuxRestoreSavedStateLabel, }; diff --git a/src/security/security_selinux.h b/src/security/security_selinux.h index 056ba75..aa67421 100644 --- a/src/security/security_selinux.h +++ b/src/security/security_selinux.h @@ -13,6 +13,6 @@ #ifndef __VIR_SECURITY_SELINUX_H__ # define __VIR_SECURITY_SELINUX_H__ -extern virSecurityDriver virSELinuxSecurityDriver; +extern virSecurityDriver virSecurityDriverSELinux; #endif /* __VIR_SECURITY_SELINUX_H__ */ diff --git a/src/security/security_stack.c b/src/security/security_stack.c new file mode 100644 index 0000000..9b3753a --- /dev/null +++ b/src/security/security_stack.c @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * QEMU stacked security driver + */ + +#include <config.h> + +#include "security_stack.h" + +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_SECURITY + +typedef struct _virSecurityStackData virSecurityStackData; +typedef virSecurityStackData *virSecurityStackDataPtr; + +struct _virSecurityStackData { + virSecurityManagerPtr primary; + virSecurityManagerPtr secondary; +}; + +void virSecurityStackSetPrimary(virSecurityManagerPtr mgr, + virSecurityManagerPtr primary) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + priv->primary = primary; +} + +void virSecurityStackSetSecondary(virSecurityManagerPtr mgr, + virSecurityManagerPtr secondary) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + priv->secondary = secondary; +} + +static virSecurityDriverStatus +virSecurityStackProbe(void) +{ + return SECURITY_DRIVER_ENABLE; +} + +static int +virSecurityStackOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +virSecurityStackClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +{ + return 0; +} + +static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + return virSecurityManagerGetModel(priv->primary); +} + +static const char * virSecurityStackGetDOI(virSecurityManagerPtr mgr) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + + return virSecurityManagerGetDOI(priv->primary); +} + +static int +virSecurityStackVerify(virSecurityManagerPtr mgr, + virDomainDefPtr def) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerVerify(priv->primary, def) < 0) + rc = -1; + +#if 0 + if (virSecurityManagerVerify(priv->secondary, def) < 0) + rc = -1; +#endif + + return rc; +} + + +static int +virSecurityStackGenLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerGenLabel(priv->primary, vm) < 0) + rc = -1; +#if 0 + if (virSecurityManagerGenLabel(priv->secondary, vm) < 0) + rc = -1; +#endif + + return rc; +} + + +static int +virSecurityStackReleaseLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0) + rc = -1; +#if 0 + if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0) + rc = -1; +#endif + + return rc; +} + + +static int +virSecurityStackReserveLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerReserveLabel(priv->primary, vm) < 0) + rc = -1; +#if 0 + if (virSecurityManagerReserveLabel(priv->secondary, vm) < 0) + rc = -1; +#endif + + return rc; +} + + +static int +virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerSetImageLabel(priv->secondary, vm, disk) < 0) + rc = -1; + if (virSecurityManagerSetImageLabel(priv->primary, vm, disk) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainDiskDefPtr disk) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerRestoreImageLabel(priv->secondary, vm, disk) < 0) + rc = -1; + if (virSecurityManagerRestoreImageLabel(priv->primary, vm, disk) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev) + +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerSetHostdevLabel(priv->secondary, vm, dev) < 0) + rc = -1; + if (virSecurityManagerSetHostdevLabel(priv->primary, vm, dev) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerRestoreHostdevLabel(priv->secondary, vm, dev) < 0) + rc = -1; + if (virSecurityManagerRestoreHostdevLabel(priv->primary, vm, dev) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *stdin_path) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerSetAllLabel(priv->secondary, vm, stdin_path) < 0) + rc = -1; + if (virSecurityManagerSetAllLabel(priv->primary, vm, stdin_path) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + int migrated) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerRestoreAllLabel(priv->secondary, vm, migrated) < 0) + rc = -1; + if (virSecurityManagerRestoreAllLabel(priv->primary, vm, migrated) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *savefile) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerSetSavedStateLabel(priv->secondary, vm, savefile) < 0) + rc = -1; + if (virSecurityManagerSetSavedStateLabel(priv->primary, vm, savefile) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + const char *savefile) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerRestoreSavedStateLabel(priv->secondary, vm, savefile) < 0) + rc = -1; + if (virSecurityManagerRestoreSavedStateLabel(priv->primary, vm, savefile) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerSetProcessLabel(priv->secondary, vm) < 0) + rc = -1; + if (virSecurityManagerSetProcessLabel(priv->primary, vm) < 0) + rc = -1; + + return rc; +} + +static int +virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm, + virSecurityLabelPtr seclabel) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + +#if 0 + if (virSecurityManagerGetProcessLabel(priv->secondary, vm, seclabel) < 0) + rc = -1; +#endif + if (virSecurityManagerGetProcessLabel(priv->primary, vm, seclabel) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerSetSocketLabel(priv->secondary, vm) < 0) + rc = -1; + if (virSecurityManagerSetSocketLabel(priv->primary, vm) < 0) + rc = -1; + + return rc; +} + + +static int +virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm) +{ + virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr); + int rc = 0; + + if (virSecurityManagerClearSocketLabel(priv->secondary, vm) < 0) + rc = -1; + if (virSecurityManagerClearSocketLabel(priv->primary, vm) < 0) + rc = -1; + + return rc; +} + + +virSecurityDriver virSecurityDriverStack = { + sizeof(virSecurityStackData), + "stack", + virSecurityStackProbe, + virSecurityStackOpen, + virSecurityStackClose, + + virSecurityStackGetModel, + virSecurityStackGetDOI, + + virSecurityStackVerify, + + virSecurityStackSetSecurityImageLabel, + virSecurityStackRestoreSecurityImageLabel, + + virSecurityStackSetSocketLabel, + virSecurityStackClearSocketLabel, + + virSecurityStackGenLabel, + virSecurityStackReserveLabel, + virSecurityStackReleaseLabel, + + virSecurityStackGetProcessLabel, + virSecurityStackSetProcessLabel, + + virSecurityStackSetSecurityAllLabel, + virSecurityStackRestoreSecurityAllLabel, + + virSecurityStackSetSecurityHostdevLabel, + virSecurityStackRestoreSecurityHostdevLabel, + + virSecurityStackSetSavedStateLabel, + virSecurityStackRestoreSavedStateLabel, +}; diff --git a/src/security/security_stack.h b/src/security/security_stack.h new file mode 100644 index 0000000..c924842 --- /dev/null +++ b/src/security/security_stack.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * QEMU stacked security driver + */ + +#include "security_driver.h" + +#ifndef __VIR_SECURITY_STACK +# define __VIR_SECURITY_STACK + +extern virSecurityDriver virSecurityDriverStack; + +void virSecurityStackSetPrimary(virSecurityManagerPtr mgr, + virSecurityManagerPtr primary); +void virSecurityStackSetSecondary(virSecurityManagerPtr mgr, + virSecurityManagerPtr secondary); + +#endif /* __VIR_SECURITY_DAC */ -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list