[libvirt] [PATCH v3] 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/libvirt.c: Add missing debug for security APIs --- po/POTFILES.in | 2 +- src/Makefile.am | 12 +- src/libvirt.c | 4 + src/libvirt_private.syms | 34 ++- src/qemu/qemu_conf.h | 6 +- src/qemu/qemu_driver.c | 167 ++++------ 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 | 713 ++++++++++++++++++++++++++++++++++++++ src/security/security_dac.h | 36 ++ src/security/security_driver.c | 125 ++----- src/security/security_driver.h | 95 +++--- src/security/security_manager.c | 317 +++++++++++++++++ src/security/security_manager.h | 95 +++++ src/security/security_nop.c | 185 ++++++++++ src/security/security_nop.h | 27 ++ src/security/security_selinux.c | 145 +++++--- src/security/security_selinux.h | 2 +- src/security/security_stack.c | 401 +++++++++++++++++++++ src/security/security_stack.h | 33 ++ 25 files changed, 2207 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/po/POTFILES.in b/po/POTFILES.in index 3d7bc8b..3521ba6 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -61,10 +61,10 @@ src/qemu/qemu_hotplug.c src/qemu/qemu_monitor.c src/qemu/qemu_monitor_json.c src/qemu/qemu_monitor_text.c -src/qemu/qemu_security_dac.c src/remote/remote_driver.c src/secret/secret_driver.c src/security/security_apparmor.c +src/security/security_dac.c src/security/security_driver.c src/security/security_selinux.c src/security/virt-aa-helper.c 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.c b/src/libvirt.c index 89b37c5..a4789bc 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5642,6 +5642,8 @@ virDomainGetSecurityLabel(virDomainPtr domain, virSecurityLabelPtr seclabel) { virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, "seclabel=%p", seclabel); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); virDispatchError(NULL); @@ -5684,6 +5686,8 @@ error: int virNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel) { + DEBUG("conn=%p secmodel=%p", conn, secmodel); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); virDispatchError(NULL); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 19e581c..e9b8cb7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -701,13 +701,33 @@ virSecretDefParseFile; virSecretDefParseString; -# security.h -virSecurityDriverGetDOI; -virSecurityDriverGetModel; -virSecurityDriverInit; -virSecurityDriverSetDOI; -virSecurityDriverStartup; -virSecurityDriverVerify; +# security_driver.h +virSecurityDriverLookup; + + +# security_manager.h +virSecurityManagerClearSocketLabel; +virSecurityManagerFree; +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..24e9162 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,35 +984,34 @@ qemuReconnectDomains(virConnectPtr conn, struct qemud_driver *driver) static int -qemudSecurityInit(struct qemud_driver *qemud_drv) +qemuSecurityInit(struct qemud_driver *driver) { - int ret; - virSecurityDriverPtr security_drv; - - qemuSecurityStackedSetDriver(qemud_drv); - qemuSecurityDACSetDriver(qemud_drv); + virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName, + driver->allowDiskFormatProbing); + if (!mgr) + goto error; - ret = virSecurityDriverStartup(&security_drv, - qemud_drv->securityDriverName, - qemud_drv->allowDiskFormatProbing); - if (ret == -1) { - VIR_ERROR0(_("Failed to start security driver")); - return -1; - } + if (driver->privileged) { + virSecurityManagerPtr dac = virSecurityManagerNewDAC(driver->user, + driver->group, + driver->allowDiskFormatProbing, + driver->dynamicOwnership); + if (!dac) + goto error; - /* 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->securityManager = virSecurityManagerNewStack(mgr, + dac))) + goto error; } 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; + +error: + VIR_ERROR0("Failed to initialize security drivers"); + virSecurityManagerFree(mgr); + return -1; } @@ -1057,21 +1045,20 @@ qemuCreateCapabilities(virCapsPtr oldcaps, } /* Security driver data */ - if (driver->securityPrimaryDriver) { - const char *doi, *model; - - doi = virSecurityDriverGetDOI(driver->securityPrimaryDriver); - model = virSecurityDriverGetModel(driver->securityPrimaryDriver); + const char *doi, *model; + doi = virSecurityManagerGetDOI(driver->securityManager); + model = virSecurityManagerGetModel(driver->securityManager); + if (STRNEQ(model, "none")) { 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; no_memory: @@ -1336,7 +1323,7 @@ qemudStartup(int privileged) { } VIR_FREE(driverConf); - if (qemudSecurityInit(qemu_driver) < 0) + if (qemuSecurityInit(qemu_driver) < 0) goto error; if ((qemu_driver->caps = qemuCreateCapabilities(NULL, @@ -1555,10 +1542,11 @@ 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); + virSecurityManagerFree(qemu_driver->securityManager); + ebtablesContextFree(qemu_driver->ebtables); if (qemu_driver->cgroupDeviceACL) { @@ -2573,9 +2561,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 +2646,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 +3037,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 +3543,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 +4446,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 +4480,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 +4523,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 +4748,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 +4781,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 +5399,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 +5424,12 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn, int ret = 0; qemuDriverLock(driver); - if (!driver->securityPrimaryDriver) { - memset(secmodel, 0, sizeof (*secmodel)); + memset(secmodel, 0, sizeof(*secmodel)); + + /* NULL indicates no driver, which we treat as + * success, but simply return no data in *secmodel */ + if (driver->caps->host.secModel.model == NULL) goto cleanup; - } p = driver->caps->host.secModel.model; if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) { @@ -5840,10 +5805,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 +6335,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..ffd8288 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..de5d011 --- /dev/null +++ b/src/security/security_dac.c @@ -0,0 +1,713 @@ +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 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 entire 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..ccd9d1c --- /dev/null +++ b/src/security/security_dac.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 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..4df73d7 100644 --- a/src/security/security_driver.c +++ b/src/security/security_driver.c @@ -14,6 +14,7 @@ #include <string.h> #include "virterror_internal.h" +#include "logging.h" #include "security_driver.h" #ifdef WITH_SECDRIVER_SELINUX @@ -24,116 +25,56 @@ # 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; + virSecurityDriverPtr drv = NULL; + int i; - if (name && STREQ(name, "none")) - return -2; + VIR_DEBUG("name=%s", NULLSTR(name)); - for (i = 0; security_drivers[i] != NULL ; i++) { + for (i = 0; i < ARRAY_CARDINALITY(security_drivers) && !drv ; 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; + } + } else { + switch (tmp->probe()) { + case SECURITY_DRIVER_ENABLE: + VIR_DEBUG("Probed name=%s", tmp->name); + drv = tmp; + break; + + case SECURITY_DRIVER_DISABLE: + VIR_DEBUG("Not enabled name=%s", tmp->name); + break; + + default: + return NULL; } - break; - - case SECURITY_DRIVER_DISABLE: - break; - - default: - return -1; } } - 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; -} - -void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv, - bool allowDiskFormatProbing) -{ - drv->_private.allowDiskFormatProbing = allowDiskFormatProbing; -} - -bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv) -{ - return drv->_private.allowDiskFormatProbing; + return drv; } 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..66cffb5 --- /dev/null +++ b/src/security/security_manager.c @@ -0,0 +1,317 @@ +/* + * security_manager.c: Internal security manager API + * + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#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)); + + if (!mgr) + return NULL; + + 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); + + if (!mgr) + return NULL; + + 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 ((char*)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..189b6b4 --- /dev/null +++ b/src/security/security_manager.h @@ -0,0 +1,95 @@ +/* + * security_manager.h: Internal security manager API + * + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#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..6d7cb47 --- /dev/null +++ b/src/security/security_nop.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#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, + "none", + 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..589a75d --- /dev/null +++ b/src/security/security_nop.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#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..e8bb058 --- /dev/null +++ b/src/security/security_stack.c @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 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 (virSecurityManagerVerify(priv->secondary, def) < 0) + rc = -1; + + 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 + /* We don't allow secondary drivers to generate labels. + * This may have to change in the future, but requires + * changes elsewhere in domain_conf.c and capabilities.c + * XML formats first, to allow recording of multiple + * labels + */ + 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 + /* XXX See note in GenLabel */ + 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 + /* XXX See note in GenLabel */ + 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..bc83ff3 --- /dev/null +++ b/src/security/security_stack.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 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/07/2011 08:39 AM, Daniel P. Berrange wrote:
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)
Can you show the changes between v2 and v3? (although if you wait long enough, I can probably generate that myself, given a few minutes of git usage, and start replying based on that...) -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/07/2011 12:15 PM, Eric Blake wrote:
On 01/07/2011 08:39 AM, Daniel P. Berrange wrote:
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)
Can you show the changes between v2 and v3? (although if you wait long enough, I can probably generate that myself, given a few minutes of git usage, and start replying based on that...)
Just did it.
diff --git a/po/POTFILES.in b/po/POTFILES.in index 3d7bc8b..3521ba6 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -61,10 +61,10 @@ src/qemu/qemu_hotplug.c src/qemu/qemu_monitor.c src/qemu/qemu_monitor_json.c src/qemu/qemu_monitor_text.c -src/qemu/qemu_security_dac.c src/remote/remote_driver.c src/secret/secret_driver.c src/security/security_apparmor.c +src/security/security_dac.c src/security/security_driver.c src/security/security_selinux.c src/security/virt-aa-helper.c
Yep, 'make syntax-check' would have complained about that. You still had one 'make syntax-check' failure in v3, though: libvirt_unmarked_diagnostics src/qemu/qemu_driver.c:1012: VIR_ERROR0("Failed to initialize security drivers"); maint.mk: found unmarked diagnostic(s)
diff --git a/src/libvirt.c b/src/libvirt.c index 89b37c5..a4789bc 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5642,6 +5642,8 @@ virDomainGetSecurityLabel(virDomainPtr domain, virSecurityLabelPtr seclabel) { virConnectPtr conn;
+ VIR_DOMAIN_DEBUG(domain, "seclabel=%p", seclabel); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); virDispatchError(NULL); @@ -5684,6 +5686,8 @@ error: int virNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel) { + DEBUG("conn=%p secmodel=%p", conn, secmodel); +
Useful changes.
if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); virDispatchError(NULL); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 279559b..e9b8cb7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -707,6 +707,7 @@ virSecurityDriverLookup;
# security_manager.h virSecurityManagerClearSocketLabel; +virSecurityManagerFree; virSecurityManagerGenLabel; virSecurityManagerGetDOI; virSecurityManagerGetModel; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0f84bb2..24e9162 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -984,12 +984,12 @@ qemuReconnectDomains(virConnectPtr conn, struct qemud_driver *driver)
static int -qemudSecurityInit(struct qemud_driver *driver) +qemuSecurityInit(struct qemud_driver *driver)
Why not, it fits with our other renames.
{ virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName, driver->allowDiskFormatProbing); if (!mgr) - return -1; + goto error;
if (driver->privileged) { virSecurityManagerPtr dac = virSecurityManagerNewDAC(driver->user, @@ -997,16 +997,21 @@ qemudSecurityInit(struct qemud_driver *driver) driver->allowDiskFormatProbing, driver->dynamicOwnership); if (!dac) - return -1; + goto error;
if (!(driver->securityManager = virSecurityManagerNewStack(mgr, dac))) - return -1; + goto error; } else { driver->securityManager = mgr; }
return 0; + +error: + VIR_ERROR0("Failed to initialize security drivers"); + virSecurityManagerFree(mgr); + return -1;
Good, fixed that concern of mine.
}
@@ -1044,16 +1049,13 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); - if (STREQ(model, "none")) { - model = ""; - doi = ""; + if (STRNEQ(model, "none")) { + 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; -
Almost; that cleaned up the chance of calling VIR_FREE on "", but...
VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi);
...if model == "none", then doi was not adjusted; do you need NULLSTR(doi) here?
@@ -1321,7 +1323,7 @@ qemudStartup(int privileged) { } VIR_FREE(driverConf);
- if (qemudSecurityInit(qemu_driver) < 0) + if (qemuSecurityInit(qemu_driver) < 0) goto error;
if ((qemu_driver->caps = qemuCreateCapabilities(NULL, @@ -1543,6 +1545,8 @@ qemudShutdown(void) { VIR_FREE(qemu_driver->saveImageFormat); VIR_FREE(qemu_driver->dumpImageFormat);
+ virSecurityManagerFree(qemu_driver->securityManager); + ebtablesContextFree(qemu_driver->ebtables);
if (qemu_driver->cgroupDeviceACL) { @@ -5420,6 +5424,12 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn, int ret = 0;
qemuDriverLock(driver); + memset(secmodel, 0, sizeof(*secmodel)); + + /* NULL indicates no driver, which we treat as + * success, but simply return no data in *secmodel */ + if (driver->caps->host.secModel.model == NULL) + goto cleanup;
p = driver->caps->host.secModel.model; if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) { diff --git a/src/security/security_apparmor.h b/src/security/security_apparmor.h index 90d9ddb..ffd8288 100644 --- a/src/security/security_apparmor.h +++ b/src/security/security_apparmor.h @@ -14,7 +14,7 @@ #ifndef __VIR_SECURITY_APPARMOR_H__ # define __VIR_SECURITY_APPARMOR_H__
-#include "security_driver.h" +# include "security_driver.h"
You must have cppi installed :) (another make syntax-check fix).
extern virSecurityDriver virAppArmorSecurityDriver;
diff --git a/src/security/security_dac.c b/src/security/security_dac.c index edecaf9..de5d011 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1,13 +1,23 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * POSIX DAC security driver */ + #include <config.h> #include <sys/types.h> #include <sys/stat.h> @@ -537,7 +547,7 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr, return 0;
for (i = 0 ; i < vm->def->ndisks ; i++) { - /* XXX fixme - we need to recursively label the entriy tree :-( */ + /* XXX fixme - we need to recursively label the entire tree :-( */ if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) continue; if (virSecurityDACSetSecurityImageLabel(mgr, diff --git a/src/security/security_dac.h b/src/security/security_dac.h index b690236..ccd9d1c 100644 --- a/src/security/security_dac.h +++ b/src/security/security_dac.h @@ -1,11 +1,20 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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. * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * POSIX DAC security driver */
diff --git a/src/security/security_driver.c b/src/security/security_driver.c index 6d75dcc..4df73d7 100644 --- a/src/security/security_driver.c +++ b/src/security/security_driver.c @@ -14,6 +14,7 @@ #include <string.h>
#include "virterror_internal.h" +#include "logging.h"
#include "security_driver.h" #ifdef WITH_SECDRIVER_SELINUX @@ -41,7 +42,9 @@ virSecurityDriverPtr virSecurityDriverLookup(const char *name) virSecurityDriverPtr drv = NULL; int i;
- for (i = 0; i < ARRAY_CARDINALITY(security_drivers) ; i++) { + VIR_DEBUG("name=%s", NULLSTR(name)); + + for (i = 0; i < ARRAY_CARDINALITY(security_drivers) && !drv ; i++) { virSecurityDriverPtr tmp = security_drivers[i];
if (name) { @@ -52,10 +55,12 @@ virSecurityDriverPtr virSecurityDriverLookup(const char *name) } else { switch (tmp->probe()) { case SECURITY_DRIVER_ENABLE: + VIR_DEBUG("Probed name=%s", tmp->name); drv = tmp; break;
case SECURITY_DRIVER_DISABLE: + VIR_DEBUG("Not enabled name=%s", tmp->name); break;
default: @@ -66,10 +71,10 @@ virSecurityDriverPtr virSecurityDriverLookup(const char *name)
if (!drv) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, - "Security driver %s not found", NULLSTR(name)); + _("Security driver %s not found"), + NULLSTR(name)); return NULL; }
return drv; } - diff --git a/src/security/security_manager.c b/src/security/security_manager.c index 7ab6e37..66cffb5 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -1,3 +1,24 @@ +/* + * security_manager.c: Internal security manager API + * + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */
#include <config.h>
@@ -45,6 +66,9 @@ virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary, virSecurityManagerNewDriver(&virSecurityDriverStack, virSecurityManagerGetAllowDiskFormatProbing(primary));
+ if (!mgr) + return NULL; + virSecurityStackSetPrimary(mgr, primary); virSecurityStackSetSecondary(mgr, secondary);
@@ -60,6 +84,9 @@ virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user, virSecurityManagerNewDriver(&virSecurityDriverDAC, allowDiskFormatProbing);
+ if (!mgr) + return NULL; + virSecurityDACSetUser(mgr, user); virSecurityDACSetGroup(mgr, group); virSecurityDACSetDynamicOwnership(mgr, dynamicOwnership); @@ -80,7 +107,7 @@ virSecurityManagerPtr virSecurityManagerNew(const char *name,
void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr) { - return mgr + sizeof(mgr); + return ((char*)mgr) + sizeof(mgr);
Definitely a good fix :)
}
@@ -288,4 +315,3 @@ int virSecurityManagerVerify(virSecurityManagerPtr mgr, virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); return -1; } - diff --git a/src/security/security_manager.h b/src/security/security_manager.h index c0ef84f..189b6b4 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -1,8 +1,29 @@ +/* + * security_manager.h: Internal security manager API + * + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */
#ifndef VIR_SECURITY_MANAGER_H__ -#define VIR_SECURITY_MANAGER_H__ +# define VIR_SECURITY_MANAGER_H__
-# define virSecurityReportError(code, ...) \ +# define virSecurityReportError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__)
diff --git a/src/security/security_nop.c b/src/security/security_nop.c index 947cf55..6d7cb47 100644 --- a/src/security/security_nop.c +++ b/src/security/security_nop.c @@ -1,4 +1,21 @@ - +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */
#include <config.h>
@@ -134,7 +151,7 @@ static int virSecurityDomainVerifyNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED
virSecurityDriver virSecurityDriverNop = { 0, - "nop", + "none",
Reasonable name change.
virSecurityDriverProbeNop, virSecurityDriverOpenNop, virSecurityDriverCloseNop, diff --git a/src/security/security_nop.h b/src/security/security_nop.h index 714e646..589a75d 100644 --- a/src/security/security_nop.h +++ b/src/security/security_nop.h @@ -1,16 +1,26 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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. * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ + #ifndef __VIR_SECURITY_NOP_H__ # define __VIR_SECURITY_NOP_H__
-#include "security_driver.h" +# include "security_driver.h"
extern virSecurityDriver virSecurityDriverNop;
diff --git a/src/security/security_stack.c b/src/security/security_stack.c index 9b3753a..e8bb058 100644 --- a/src/security/security_stack.c +++ b/src/security/security_stack.c @@ -1,12 +1,21 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Stacked security driver */
#include <config.h> @@ -57,14 +66,16 @@ virSecurityStackClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) return 0; }
-static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr) +static const char * +virSecurityStackGetModel(virSecurityManagerPtr mgr) { virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
return virSecurityManagerGetModel(priv->primary); }
-static const char * virSecurityStackGetDOI(virSecurityManagerPtr mgr) +static const char * +virSecurityStackGetDOI(virSecurityManagerPtr mgr) { virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
@@ -81,10 +92,8 @@ virSecurityStackVerify(virSecurityManagerPtr mgr, if (virSecurityManagerVerify(priv->primary, def) < 0) rc = -1;
-#if 0 if (virSecurityManagerVerify(priv->secondary, def) < 0) rc = -1; -#endif
return rc; } @@ -99,7 +108,14 @@ virSecurityStackGenLabel(virSecurityManagerPtr mgr,
if (virSecurityManagerGenLabel(priv->primary, vm) < 0) rc = -1; + #if 0 + /* We don't allow secondary drivers to generate labels. + * This may have to change in the future, but requires + * changes elsewhere in domain_conf.c and capabilities.c + * XML formats first, to allow recording of multiple + * labels + */ if (virSecurityManagerGenLabel(priv->secondary, vm) < 0) rc = -1; #endif @@ -118,6 +134,7 @@ virSecurityStackReleaseLabel(virSecurityManagerPtr mgr, if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0) rc = -1; #if 0 + /* XXX See note in GenLabel */ if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0) rc = -1; #endif @@ -136,6 +153,7 @@ virSecurityStackReserveLabel(virSecurityManagerPtr mgr, if (virSecurityManagerReserveLabel(priv->primary, vm) < 0) rc = -1; #if 0 + /* XXX See note in GenLabel */ if (virSecurityManagerReserveLabel(priv->secondary, vm) < 0) rc = -1;
Thanks - those extra comments help justify the #if 0.
#endif diff --git a/src/security/security_stack.h b/src/security/security_stack.h index c924842..bc83ff3 100644 --- a/src/security/security_stack.h +++ b/src/security/security_stack.h @@ -1,12 +1,21 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Stacked security driver */
#include "security_driver.h"
And 'make check' is still failing: cc1: warnings being treated as errors seclabeltest.c: In function 'main': seclabeltest.c:18:5: error: implicit declaration of function 'virSecurityDriverStartup' [-Wimplicit-function-declaration] seclabeltest.c:18:5: error: nested extern declaration of 'virSecurityDriverStartup' [-Wnested-externs] seclabeltest.c:28:13: error: expected expression before 'virSecurityDriverGetModel' seclabeltest.c:36:11: error: expected expression before 'virSecurityDriverGetDOI' I'm not sure how much work will go into cleaning up that test to reflect the refactorings, but I trust that you can handle it without me having to review that portion. Conditional ACK, without needing to post v4 (unless you want to), once you fix the remaining 'make syntax-check check' fallout. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Jan 07, 2011 at 12:29:40PM -0700, Eric Blake wrote:
On 01/07/2011 12:15 PM, Eric Blake wrote:
On 01/07/2011 08:39 AM, Daniel P. Berrange wrote:
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)
Can you show the changes between v2 and v3? (although if you wait long enough, I can probably generate that myself, given a few minutes of git usage, and start replying based on that...)
Just did it.
diff --git a/po/POTFILES.in b/po/POTFILES.in index 3d7bc8b..3521ba6 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -61,10 +61,10 @@ src/qemu/qemu_hotplug.c src/qemu/qemu_monitor.c src/qemu/qemu_monitor_json.c src/qemu/qemu_monitor_text.c -src/qemu/qemu_security_dac.c src/remote/remote_driver.c src/secret/secret_driver.c src/security/security_apparmor.c +src/security/security_dac.c src/security/security_driver.c src/security/security_selinux.c src/security/virt-aa-helper.c
Yep, 'make syntax-check' would have complained about that. You still had one 'make syntax-check' failure in v3, though:
libvirt_unmarked_diagnostics src/qemu/qemu_driver.c:1012: VIR_ERROR0("Failed to initialize security drivers"); maint.mk: found unmarked diagnostic(s)
diff --git a/src/libvirt.c b/src/libvirt.c index 89b37c5..a4789bc 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5642,6 +5642,8 @@ virDomainGetSecurityLabel(virDomainPtr domain, virSecurityLabelPtr seclabel) { virConnectPtr conn;
+ VIR_DOMAIN_DEBUG(domain, "seclabel=%p", seclabel); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); virDispatchError(NULL); @@ -5684,6 +5686,8 @@ error: int virNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel) { + DEBUG("conn=%p secmodel=%p", conn, secmodel); +
Useful changes.
if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); virDispatchError(NULL); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 279559b..e9b8cb7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -707,6 +707,7 @@ virSecurityDriverLookup;
# security_manager.h virSecurityManagerClearSocketLabel; +virSecurityManagerFree; virSecurityManagerGenLabel; virSecurityManagerGetDOI; virSecurityManagerGetModel; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0f84bb2..24e9162 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -984,12 +984,12 @@ qemuReconnectDomains(virConnectPtr conn, struct qemud_driver *driver)
static int -qemudSecurityInit(struct qemud_driver *driver) +qemuSecurityInit(struct qemud_driver *driver)
Why not, it fits with our other renames.
{ virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName, driver->allowDiskFormatProbing); if (!mgr) - return -1; + goto error;
if (driver->privileged) { virSecurityManagerPtr dac = virSecurityManagerNewDAC(driver->user, @@ -997,16 +997,21 @@ qemudSecurityInit(struct qemud_driver *driver) driver->allowDiskFormatProbing, driver->dynamicOwnership); if (!dac) - return -1; + goto error;
if (!(driver->securityManager = virSecurityManagerNewStack(mgr, dac))) - return -1; + goto error; } else { driver->securityManager = mgr; }
return 0; + +error: + VIR_ERROR0("Failed to initialize security drivers"); + virSecurityManagerFree(mgr); + return -1;
Good, fixed that concern of mine.
}
@@ -1044,16 +1049,13 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); - if (STREQ(model, "none")) { - model = ""; - doi = ""; + if (STRNEQ(model, "none")) { + 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; -
Almost; that cleaned up the chance of calling VIR_FREE on "", but...
VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi);
...if model == "none", then doi was not adjusted; do you need NULLSTR(doi) here?
@@ -1321,7 +1323,7 @@ qemudStartup(int privileged) { } VIR_FREE(driverConf);
- if (qemudSecurityInit(qemu_driver) < 0) + if (qemuSecurityInit(qemu_driver) < 0) goto error;
if ((qemu_driver->caps = qemuCreateCapabilities(NULL, @@ -1543,6 +1545,8 @@ qemudShutdown(void) { VIR_FREE(qemu_driver->saveImageFormat); VIR_FREE(qemu_driver->dumpImageFormat);
+ virSecurityManagerFree(qemu_driver->securityManager); + ebtablesContextFree(qemu_driver->ebtables);
if (qemu_driver->cgroupDeviceACL) { @@ -5420,6 +5424,12 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn, int ret = 0;
qemuDriverLock(driver); + memset(secmodel, 0, sizeof(*secmodel)); + + /* NULL indicates no driver, which we treat as + * success, but simply return no data in *secmodel */ + if (driver->caps->host.secModel.model == NULL) + goto cleanup;
p = driver->caps->host.secModel.model; if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) { diff --git a/src/security/security_apparmor.h b/src/security/security_apparmor.h index 90d9ddb..ffd8288 100644 --- a/src/security/security_apparmor.h +++ b/src/security/security_apparmor.h @@ -14,7 +14,7 @@ #ifndef __VIR_SECURITY_APPARMOR_H__ # define __VIR_SECURITY_APPARMOR_H__
-#include "security_driver.h" +# include "security_driver.h"
You must have cppi installed :) (another make syntax-check fix).
extern virSecurityDriver virAppArmorSecurityDriver;
diff --git a/src/security/security_dac.c b/src/security/security_dac.c index edecaf9..de5d011 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1,13 +1,23 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * POSIX DAC security driver */ + #include <config.h> #include <sys/types.h> #include <sys/stat.h> @@ -537,7 +547,7 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr, return 0;
for (i = 0 ; i < vm->def->ndisks ; i++) { - /* XXX fixme - we need to recursively label the entriy tree :-( */ + /* XXX fixme - we need to recursively label the entire tree :-( */ if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) continue; if (virSecurityDACSetSecurityImageLabel(mgr, diff --git a/src/security/security_dac.h b/src/security/security_dac.h index b690236..ccd9d1c 100644 --- a/src/security/security_dac.h +++ b/src/security/security_dac.h @@ -1,11 +1,20 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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. * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * POSIX DAC security driver */
diff --git a/src/security/security_driver.c b/src/security/security_driver.c index 6d75dcc..4df73d7 100644 --- a/src/security/security_driver.c +++ b/src/security/security_driver.c @@ -14,6 +14,7 @@ #include <string.h>
#include "virterror_internal.h" +#include "logging.h"
#include "security_driver.h" #ifdef WITH_SECDRIVER_SELINUX @@ -41,7 +42,9 @@ virSecurityDriverPtr virSecurityDriverLookup(const char *name) virSecurityDriverPtr drv = NULL; int i;
- for (i = 0; i < ARRAY_CARDINALITY(security_drivers) ; i++) { + VIR_DEBUG("name=%s", NULLSTR(name)); + + for (i = 0; i < ARRAY_CARDINALITY(security_drivers) && !drv ; i++) { virSecurityDriverPtr tmp = security_drivers[i];
if (name) { @@ -52,10 +55,12 @@ virSecurityDriverPtr virSecurityDriverLookup(const char *name) } else { switch (tmp->probe()) { case SECURITY_DRIVER_ENABLE: + VIR_DEBUG("Probed name=%s", tmp->name); drv = tmp; break;
case SECURITY_DRIVER_DISABLE: + VIR_DEBUG("Not enabled name=%s", tmp->name); break;
default: @@ -66,10 +71,10 @@ virSecurityDriverPtr virSecurityDriverLookup(const char *name)
if (!drv) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, - "Security driver %s not found", NULLSTR(name)); + _("Security driver %s not found"), + NULLSTR(name)); return NULL; }
return drv; } - diff --git a/src/security/security_manager.c b/src/security/security_manager.c index 7ab6e37..66cffb5 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -1,3 +1,24 @@ +/* + * security_manager.c: Internal security manager API + * + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */
#include <config.h>
@@ -45,6 +66,9 @@ virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary, virSecurityManagerNewDriver(&virSecurityDriverStack, virSecurityManagerGetAllowDiskFormatProbing(primary));
+ if (!mgr) + return NULL; + virSecurityStackSetPrimary(mgr, primary); virSecurityStackSetSecondary(mgr, secondary);
@@ -60,6 +84,9 @@ virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user, virSecurityManagerNewDriver(&virSecurityDriverDAC, allowDiskFormatProbing);
+ if (!mgr) + return NULL; + virSecurityDACSetUser(mgr, user); virSecurityDACSetGroup(mgr, group); virSecurityDACSetDynamicOwnership(mgr, dynamicOwnership); @@ -80,7 +107,7 @@ virSecurityManagerPtr virSecurityManagerNew(const char *name,
void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr) { - return mgr + sizeof(mgr); + return ((char*)mgr) + sizeof(mgr);
Definitely a good fix :)
}
@@ -288,4 +315,3 @@ int virSecurityManagerVerify(virSecurityManagerPtr mgr, virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__); return -1; } - diff --git a/src/security/security_manager.h b/src/security/security_manager.h index c0ef84f..189b6b4 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -1,8 +1,29 @@ +/* + * security_manager.h: Internal security manager API + * + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */
#ifndef VIR_SECURITY_MANAGER_H__ -#define VIR_SECURITY_MANAGER_H__ +# define VIR_SECURITY_MANAGER_H__
-# define virSecurityReportError(code, ...) \ +# define virSecurityReportError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__)
diff --git a/src/security/security_nop.c b/src/security/security_nop.c index 947cf55..6d7cb47 100644 --- a/src/security/security_nop.c +++ b/src/security/security_nop.c @@ -1,4 +1,21 @@ - +/* + * Copyright (C) 2010-2011 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */
#include <config.h>
@@ -134,7 +151,7 @@ static int virSecurityDomainVerifyNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED
virSecurityDriver virSecurityDriverNop = { 0, - "nop", + "none",
Reasonable name change.
virSecurityDriverProbeNop, virSecurityDriverOpenNop, virSecurityDriverCloseNop, diff --git a/src/security/security_nop.h b/src/security/security_nop.h index 714e646..589a75d 100644 --- a/src/security/security_nop.h +++ b/src/security/security_nop.h @@ -1,16 +1,26 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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. * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ + #ifndef __VIR_SECURITY_NOP_H__ # define __VIR_SECURITY_NOP_H__
-#include "security_driver.h" +# include "security_driver.h"
extern virSecurityDriver virSecurityDriverNop;
diff --git a/src/security/security_stack.c b/src/security/security_stack.c index 9b3753a..e8bb058 100644 --- a/src/security/security_stack.c +++ b/src/security/security_stack.c @@ -1,12 +1,21 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Stacked security driver */
#include <config.h> @@ -57,14 +66,16 @@ virSecurityStackClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) return 0; }
-static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr) +static const char * +virSecurityStackGetModel(virSecurityManagerPtr mgr) { virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
return virSecurityManagerGetModel(priv->primary); }
-static const char * virSecurityStackGetDOI(virSecurityManagerPtr mgr) +static const char * +virSecurityStackGetDOI(virSecurityManagerPtr mgr) { virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
@@ -81,10 +92,8 @@ virSecurityStackVerify(virSecurityManagerPtr mgr, if (virSecurityManagerVerify(priv->primary, def) < 0) rc = -1;
-#if 0 if (virSecurityManagerVerify(priv->secondary, def) < 0) rc = -1; -#endif
return rc; } @@ -99,7 +108,14 @@ virSecurityStackGenLabel(virSecurityManagerPtr mgr,
if (virSecurityManagerGenLabel(priv->primary, vm) < 0) rc = -1; + #if 0 + /* We don't allow secondary drivers to generate labels. + * This may have to change in the future, but requires + * changes elsewhere in domain_conf.c and capabilities.c + * XML formats first, to allow recording of multiple + * labels + */ if (virSecurityManagerGenLabel(priv->secondary, vm) < 0) rc = -1; #endif @@ -118,6 +134,7 @@ virSecurityStackReleaseLabel(virSecurityManagerPtr mgr, if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0) rc = -1; #if 0 + /* XXX See note in GenLabel */ if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0) rc = -1; #endif @@ -136,6 +153,7 @@ virSecurityStackReserveLabel(virSecurityManagerPtr mgr, if (virSecurityManagerReserveLabel(priv->primary, vm) < 0) rc = -1; #if 0 + /* XXX See note in GenLabel */ if (virSecurityManagerReserveLabel(priv->secondary, vm) < 0) rc = -1;
Thanks - those extra comments help justify the #if 0.
#endif diff --git a/src/security/security_stack.h b/src/security/security_stack.h index c924842..bc83ff3 100644 --- a/src/security/security_stack.h +++ b/src/security/security_stack.h @@ -1,12 +1,21 @@ /* - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Stacked security driver */
#include "security_driver.h"
And 'make check' is still failing:
Urgh, I really hate that a simple 'make' no longer builds the test suite :-( Daniel
participants (2)
-
Daniel P. Berrange
-
Eric Blake