[libvirt] [PATCH] Refactor the security drivers to simplify usage

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

On 01/06/2011 05:35 AM, Daniel P. Berrange wrote:
The current security driver usage requires horrible code like
if (driver->securityDriver && driver->securityDriver->domainSetSecurityHostdevLabel && driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver, vm, hostdev) < 0)
This is a v2 of the earlier https://www.redhat.com/archives/libvir-list/2010-November/msg00984.html, but omits the rest of the 8-patch series that v1 was included with. That's okay, but I'm a bit curious on the progress of the rest of that series (in part because it involved adding virCommand handshaking, where I'm not sure if I need to lend a hand at getting that in) :)
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)
-qemudSecurityInit(struct qemud_driver *qemud_drv) +qemudSecurityInit(struct qemud_driver *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;
Does this leak mgr?
+ + if (!(driver->securityManager = virSecurityManagerNewStack(mgr, + dac))) + return -1;
Likewise.
@@ -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);
Is there any state in a virSecurityManagerPtr that might necessitate a cleanup function (and even if there isn't right now, what happens if we extend virSecurityManager in the future), such that you are missing a call here to virSecurityManagerFree(qemu_driver->securityManager)?
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.
Add 2011 and/or Red Hat copyright annotations?
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.
2010-2011
+ * + * 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
Do we still need the term QEMU here, or should it be dropped now that it's generic?
+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);
%d and uid/gid are not compatible on cygwin; in util/util.c, we use %u, (unsigned int)uid for a portable alternative. (I'm not sure if this file would end up being compiled on cygwin, even though the old qemu version has been skipped to date). Multiple instances, but worth a separate cleanup patch, similar to commit c685993d7, so that this (already large) patch remains as a straight code motion with no hidden cleanup.
+ +static int +virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, + const char *path, + size_t depth ATTRIBUTE_UNUSED, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
Rather than passing mgr as opaque, and recomputing priv each time through the loop, ...
+ + 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);
why not just pass priv as opaque in the first place?
+static int +virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+static int +virSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+static int +virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev) +{ + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr);
+ ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr);
Likewise.
+ +static int +virSecurityDACRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque ATTRIBUTE_UNUSED) +{ + return virSecurityDACRestoreSecurityFileLabel(file);
+static int +virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev) + +{
+ ret = usbDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr);
Why pass mgr, when it is unused, and when the pre-code-motion version passed NULL?
+ /* XXX fixme - we need to recursively label the entriy tree :-( */
Faithful copy of the typo (s/entriy/entire/)
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.
2010-2011
+ +void virSecurityDACSetUser(virSecurityManagerPtr mgr, + uid_t user); +void virSecurityDACSetGroup(virSecurityManagerPtr mgr, + gid_t group); + +void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr, + bool dynamic);
Setters, but no getters. I guess that's okay for now.
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 @@
No copyright header?
+virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary, + virSecurityManagerPtr secondary) +{ + virSecurityManagerPtr mgr = + virSecurityManagerNewDriver(&virSecurityDriverStack, + virSecurityManagerGetAllowDiskFormatProbing(primary));
Should this be virSecurityManagerGetAllowDiskFormatProbing(primary) || virSecurityManagerGetAllowDiskFormatProbing(secondary) or is the intent that creating a stack allows you to override probing permitted in the secondary with a primary that disables probing?
+ + virSecurityStackSetPrimary(mgr, primary); + virSecurityStackSetSecondary(mgr, secondary);
You need an early exit if mgr is NULL, since virSecurityStackSetPrimary isn't too happy with a NULL mgr.
+virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user, + gid_t group, + bool allowDiskFormatProbing, + bool dynamicOwnership) +{ + virSecurityManagerPtr mgr = + virSecurityManagerNewDriver(&virSecurityDriverDAC, + allowDiskFormatProbing); + + virSecurityDACSetUser(mgr, user);
Likewise about needing an early exit if mgr is NULL.
+void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr) +{ + return mgr + sizeof(mgr);
Won't work. You meant to do: return (char *) mgr + sizeof(mgr); otherwise, you are doing pointer arithmetic on pointers that are sizeof(mgr) large, and accessing (WAAAY) beyond array bounds. (I'm surprised it didn't dump core on you during testing.) And yes, I meant to cast to (char*), even though the return type is (void*), since pointer arithmetic on (void*) is a gcc extension not required by C99.
+void virSecurityManagerFree(virSecurityManagerPtr mgr)
This function was not exported. (Hmm, it answers my earlier question about qemu cleanup failing to call this function).
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__
No copyright header?
+#define VIR_SECURITY_MANAGER_H__ + +# define virSecurityReportError(code, ...) \ + virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__)
Line up those \.
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>
No copyright header?
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.
s/2010/2011/ (unlike other headers where you are doing code motion and preserving the old copyright years, this file is completely new)
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.
2010-2011
+ +static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr)
Unusual formatting; I'd expect either: static const char *virSecurityStackGetModel(virSecurityManagerPtr mgr) or static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr)
+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
What happened here? The original code verified the secondary driver first, not second, and here, you aren't even verifying the secondary driver. Are you really fixing a bug in the original code? If so, can we separate the bug fix from the code motion into two commits?
+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
Likewise. Here, it makes a bit more sense that you only need to generate one label to be shared among both stacks, rather than two. But what if the primary doesn't care about labels while the secondary does - shouldn't you have a fallback in that case? The next couple of functions have similar #ifdef 0 questions.
+ + +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;
The rest of this file better matches my expectations of just code motion.
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.
2010-2011
+ +void virSecurityStackSetPrimary(virSecurityManagerPtr mgr, + virSecurityManagerPtr primary); +void virSecurityStackSetSecondary(virSecurityManagerPtr mgr, + virSecurityManagerPtr secondary);
Again, setters with no getters, but I'm okay with that for now. I had enough comments (including real bugs) that it's probably worth a v3. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/06/2011 11:21 AM, Eric Blake wrote:
On 01/06/2011 05:35 AM, Daniel P. Berrange wrote:
The current security driver usage requires horrible code like
if (driver->securityDriver && driver->securityDriver->domainSetSecurityHostdevLabel && driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver, vm, hostdev) < 0)
This is a v2 of the earlier https://www.redhat.com/archives/libvir-list/2010-November/msg00984.html, but omits the rest of the 8-patch series that v1 was included with. That's okay, but I'm a bit curious on the progress of the rest of that series (in part because it involved adding virCommand handshaking, where I'm not sure if I need to lend a hand at getting that in) :)
Also lacking - my review of v1 pointed out[1] that this failed 'make syntax-check' and 'make check'; and that still appears to be the case with this v2. [1] https://www.redhat.com/archives/libvir-list/2010-November/msg01079.html -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Thu, Jan 06, 2011 at 11:21:45AM -0700, Eric Blake wrote:
On 01/06/2011 05:35 AM, Daniel P. Berrange wrote:
The current security driver usage requires horrible code like
if (driver->securityDriver && driver->securityDriver->domainSetSecurityHostdevLabel && driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver, vm, hostdev) < 0)
This is a v2 of the earlier https://www.redhat.com/archives/libvir-list/2010-November/msg00984.html, but omits the rest of the 8-patch series that v1 was included with. That's okay, but I'm a bit curious on the progress of the rest of that series (in part because it involved adding virCommand handshaking, where I'm not sure if I need to lend a hand at getting that in) :)
This security driver patch is proving a total PITA to rebase with people changes, so I want to get it merged ASAP independant of the rest of the locking changes.
- /* 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;
Does this leak mgr?
+ + if (!(driver->securityManager = virSecurityManagerNewStack(mgr, + dac))) + return -1;
Likewise.
Yep, both fixed.
@@ -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);
Is there any state in a virSecurityManagerPtr that might necessitate a cleanup function (and even if there isn't right now, what happens if we extend virSecurityManager in the future), such that you are missing a call here to virSecurityManagerFree(qemu_driver->securityManager)?
Three was a missing call to virSecurityManagerFree
+ * + * 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
Do we still need the term QEMU here, or should it be dropped now that it's generic?
That's dropped.
+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);
%d and uid/gid are not compatible on cygwin; in util/util.c, we use %u, (unsigned int)uid for a portable alternative. (I'm not sure if this file would end up being compiled on cygwin, even though the old qemu version has been skipped to date). Multiple instances, but worth a separate cleanup patch, similar to commit c685993d7, so that this (already large) patch remains as a straight code motion with no hidden cleanup.
%d does work here, because uid/gid are both declared as ints, not uid_t/gid_t.
+static int +virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, + const char *path, + size_t depth ATTRIBUTE_UNUSED, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
Rather than passing mgr as opaque, and recomputing priv each time through the loop, ...
There's no serious overhead there, so I prefer to pass the full object around.
+ +void virSecurityDACSetUser(virSecurityManagerPtr mgr, + uid_t user); +void virSecurityDACSetGroup(virSecurityManagerPtr mgr, + gid_t group); + +void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr, + bool dynamic);
Setters, but no getters. I guess that's okay for now.
There's no compelling need for any getters in this code.
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 @@
No copyright header?
+virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary, + virSecurityManagerPtr secondary) +{ + virSecurityManagerPtr mgr = + virSecurityManagerNewDriver(&virSecurityDriverStack, + virSecurityManagerGetAllowDiskFormatProbing(primary));
Should this be virSecurityManagerGetAllowDiskFormatProbing(primary) || virSecurityManagerGetAllowDiskFormatProbing(secondary)
or is the intent that creating a stack allows you to override probing permitted in the secondary with a primary that disables probing?
All drivers should have the same probe setting so it only needs to check the primary driver.
+ + virSecurityStackSetPrimary(mgr, primary); + virSecurityStackSetSecondary(mgr, secondary);
You need an early exit if mgr is NULL, since virSecurityStackSetPrimary isn't too happy with a NULL mgr.
Yep, fixed.
+virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user, + gid_t group, + bool allowDiskFormatProbing, + bool dynamicOwnership) +{ + virSecurityManagerPtr mgr = + virSecurityManagerNewDriver(&virSecurityDriverDAC, + allowDiskFormatProbing); + + virSecurityDACSetUser(mgr, user);
Likewise about needing an early exit if mgr is NULL.
+void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr) +{ + return mgr + sizeof(mgr);
Won't work. You meant to do:
return (char *) mgr + sizeof(mgr);
Strange how it actually worked, but that must have been luck, or perhaps I mistakenly didn't have the DAC driver active when i tested it first.
static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr)
+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
What happened here? The original code verified the secondary driver first, not second, and here, you aren't even verifying the secondary driver. Are you really fixing a bug in the original code? If so, can we separate the bug fix from the code motion into two commits?
I enabled the second verify even though none of the secondary drivers implement it.
+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
Likewise. Here, it makes a bit more sense that you only need to generate one label to be shared among both stacks, rather than two. But what if the primary doesn't care about labels while the secondary does - shouldn't you have a fallback in that case?
Our architecture only allows for a single label, so we can't allow secondary drivers to generate labels. We do actually want to enable this in the future though. So I've added a comment about it. All the things you mention should be fixed in v3, along with a few other minor bugs I discovered after more testing Daniel
participants (2)
-
Daniel P. Berrange
-
Eric Blake