qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- int ret;
+ int ret = -1;
/* Hold an extra reference because we can't allow 'vm' to be
* deleted while the monitor is active */
virDomainObjRef(vm);
+ if ((driver->securityDriver &&
+ driver->securityDriver->domainSetSecuritySocketLabel &&
+ driver->securityDriver->domainSetSecuritySocketLabel(driver->securityDriver,vm)) < 0) {
+ VIR_ERROR(_("Failed to set security context for monitor for %s"), vm->def->name);
+ goto error;
+ }
+
if ((priv->mon = qemuMonitorOpen(vm,
priv->monConfig,
priv->monJSON,
&monitorCallbacks)) == NULL) {
VIR_ERROR(_("Failed to connect monitor for %s"), vm->def->name);
- return -1;
+ goto error;
+ }
+
+ if ((driver->securityDriver &&
+ driver->securityDriver->domainClearSecuritySocketLabel &&
+ driver->securityDriver->domainClearSecuritySocketLabel(driver->securityDriver,vm)) < 0) {
+ VIR_ERROR(_("Failed to set security context for monitor for %s"), vm->def->name);
+ goto error;
}
qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorSetCapabilities(priv->mon);
qemuDomainObjExitMonitorWithDriver(driver, vm);
+ ret = 0;
+error:
if (ret < 0) {
qemuMonitorClose(priv->mon);
priv->mon = NULL;
+ virDomainObjUnref(vm);
}
return ret;
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,
.domainSetSavedStateLabel = qemuSecurityStackedSetSavedStateLabel,
.domainRestoreSavedStateLabel = qemuSecurityStackedRestoreSavedStateLabel,
+
+ .domainClearSecuritySocketLabel = qemuSecurityStackedClearSocketLabel,
+ .domainSetSecuritySocketLabel = qemuSecurityStackedSetSocketLabel,
};
typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv);
typedef int (*virSecurityDomainRestoreImageLabel) (virDomainObjPtr vm,
virDomainDiskDefPtr disk);
+typedef int (*virSecurityDomainSetSocketLabel) (virSecurityDriverPtr drv,
+ virDomainObjPtr vm);
+typedef int (*virSecurityDomainClearSocketLabel)(virSecurityDriverPtr drv,
+ virDomainObjPtr vm);
typedef int (*virSecurityDomainSetImageLabel) (virDomainObjPtr vm,
virDomainDiskDefPtr disk);
typedef int (*virSecurityDomainRestoreHostdevLabel) (virDomainObjPtr vm,
virSecurityDriverOpen open;
virSecurityDomainSecurityVerify domainSecurityVerify;
virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel;
+ virSecurityDomainSetSocketLabel domainSetSecuritySocketLabel;
+ virSecurityDomainClearSocketLabel domainClearSecuritySocketLabel;
virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
virSecurityDomainGenLabel domainGenSecurityLabel;
virSecurityDomainReserveLabel domainReserveSecurityLabel;
return 0;
}
+static int
+SELinuxSetSecuritySocketLabel(virSecurityDriverPtr drv,
+ virDomainObjPtr vm)
+{
+ /* TODO: verify DOI */
+ const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+ context_t execcon = NULL;
+ context_t proccon = NULL;
+ security_context_t scon = NULL;
+ int rc = -1;
+
+ if (vm->def->seclabel.label == NULL)
+ return 0;
+
+ if (!STREQ(drv->name, 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);
+ goto done;
+ }
+
+ if ( !(execcon = context_new(secdef->label)) ) {
+ virReportSystemError(errno,
+ _("unable to allocate socket security context '%s'"),
+ secdef->label);
+ goto done;
+ }
+
+ if (getcon(&scon) == -1) {
+ virReportSystemError(errno,
+ _("unable to get current process context '%s'"),
+ secdef->label);
+ goto done;
+ }
+
+ if ( !(proccon = context_new(scon)) ) {
+ virReportSystemError(errno,
+ _("unable to set socket security context '%s'"),
+ secdef->label);
+ goto done;
+ }
+
+ if (context_range_set(proccon, context_range_get(execcon)) == -1) {
+ virReportSystemError(errno,
+ _("unable to set socket security context range '%s'"),
+ secdef->label);
+ goto done;
+ }
+
+ VIR_DEBUG("Setting VM %s socket context %s",
+ vm->def->name, context_str(proccon));
+ if (setsockcreatecon(context_str(proccon)) == -1) {
+ virReportSystemError(errno,
+ _("unable to set socket security context '%s'"),
+ context_str(proccon));
+ goto done;
+ }
+
+ rc = 0;
+done:
+
+ if (security_getenforce() != 1)
+ rc = 0;
+ if (execcon) context_free(execcon);
+ if (proccon) context_free(proccon);
+ freecon(scon);
+ return rc;
+}
+
+static int
+SELinuxClearSecuritySocketLabel(virSecurityDriverPtr drv,
+ virDomainObjPtr vm)
+{
+ /* TODO: verify DOI */
+ const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+
+ if (vm->def->seclabel.label == NULL)
+ return 0;
+
+ if (!STREQ(drv->name, 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);
+ if (security_getenforce() == 1)
+ return -1;
+ }
+
+ if (setsockcreatecon(NULL) == -1) {
+ virReportSystemError(errno,
+ _("unable to clear socket security context '%s'"),
+ secdef->label);
+ if (security_getenforce() == 1)
+ return -1;
+ }
+ return 0;
+}
+
static int
SELinuxSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path ATTRIBUTE_UNUSED)
{
.open = SELinuxSecurityDriverOpen,
.domainSecurityVerify = SELinuxSecurityVerify,
.domainSetSecurityImageLabel = SELinuxSetSecurityImageLabel,
+ .domainSetSecuritySocketLabel = SELinuxSetSecuritySocketLabel,
+ .domainClearSecuritySocketLabel = SELinuxClearSecuritySocketLabel,
.domainRestoreSecurityImageLabel = SELinuxRestoreSecurityImageLabel,
.domainGenSecurityLabel = SELinuxGenSecurityLabel,
.domainReserveSecurityLabel = SELinuxReserveSecurityLabel,