@@ -684,7 +684,26 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
virCommandSetErrorBuffer(cmd, &errbuf);
- if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
+ if (virSecurityManagerSetTPMLabels(driver->securityManager,
+ def) < 0)
+ goto cleanup;
+
+ if (virSecurityManagerSetChildProcessLabel(driver->securityManager,
+ def, cmd) < 0)
+ goto cleanup;
+
+ if (virSecurityManagerPreFork(driver->securityManager) < 0)
+ goto cleanup;
+
+ /* make sure we run this with the appropriate user */
+ virCommandSetUID(cmd, cfg->swtpm_user);
+ virCommandSetGID(cmd, cfg->swtpm_group);
+
+ ret = virCommandRun(cmd, &exitstatus);
+
+ virSecurityManagerPostFork(driver->securityManager);
+
+ if (ret < 0 || exitstatus != 0) {
VIR_ERROR(_("Could not start 'swtpm'. exitstatus: %d "
"stderr: %s"), exitstatus, errbuf);
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -696,6 +715,8 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
ret = 0;
cleanup:
+ if (ret < 0)
+ virSecurityManagerRestoreTPMLabels(driver->securityManager, def);
VIR_FREE(shortName);
VIR_FREE(errbuf);
virCommandFree(cmd);
@@ -741,6 +762,7 @@ qemuExtTPMStop(virQEMUDriverPtr driver,
goto cleanup;
qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName);
+ virSecurityManagerRestoreTPMLabels(driver->securityManager, def);
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
case VIR_DOMAIN_TPM_TYPE_LAST:
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index 95e7c4d..cbf0ecf 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -149,6 +149,10 @@ typedef int (*virSecurityDomainRestoreChardevLabel) (virSecurityManagerPtr mgr,
virDomainDefPtr def,
virDomainChrSourceDefPtr dev_source,
bool chardevStdioLogd);
+typedef int (*virSecurityDomainSetTPMLabels) (virSecurityManagerPtr mgr,
+ virDomainDefPtr def);
+typedef int (*virSecurityDomainRestoreTPMLabels) (virSecurityManagerPtr mgr,
+ virDomainDefPtr def);
struct _virSecurityDriver {
@@ -213,6 +217,9 @@ struct _virSecurityDriver {
virSecurityDomainSetChardevLabel domainSetSecurityChardevLabel;
virSecurityDomainRestoreChardevLabel domainRestoreSecurityChardevLabel;
+
+ virSecurityDomainSetTPMLabels domainSetSecurityTPMLabels;
+ virSecurityDomainRestoreTPMLabels domainRestoreSecurityTPMLabels;
};
virSecurityDriverPtr virSecurityDriverLookup(const char *name,
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index 71f7f59..8683ad7 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -1204,3 +1204,39 @@ virSecurityManagerRestoreChardevLabel(virSecurityManagerPtr mgr,
virReportUnsupportedError();
return -1;
}
+
+
+int
+virSecurityManagerSetTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm)
+{
+ int ret;
+
+ if (mgr->drv->domainSetSecurityTPMLabels) {
+ virObjectLock(mgr);
+ ret = mgr->drv->domainSetSecurityTPMLabels(mgr, vm);
+ virObjectUnlock(mgr);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+
+int
+virSecurityManagerRestoreTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm)
+{
+ int ret;
+
+ if (mgr->drv->domainRestoreSecurityTPMLabels) {
+ virObjectLock(mgr);
+ ret = mgr->drv->domainRestoreSecurityTPMLabels(mgr, vm);
+ virObjectUnlock(mgr);
+
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index c36a8b4..e772b61 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -194,4 +194,10 @@ int virSecurityManagerRestoreChardevLabel(virSecurityManagerPtr mgr,
virDomainChrSourceDefPtr dev_source,
bool chardevStdioLogd);
+int virSecurityManagerSetTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm);
+
+int virSecurityManagerRestoreTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm);
+
#endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 92e8415..6377fb7 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -3048,6 +3048,167 @@ virSecuritySELinuxDomainSetPathLabel(virSecurityManagerPtr mgr,
return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel);
}
+
+/*
+ * _virSecuritySELinuxSetFileLabels:
+ *
+ * @mgr: the virSecurityManager
+ * @path: path to a directory or a file
+ * @seclabel: the security label
+ *
+ * Set the file labels on the given path; if the path is a directory
+ * we label all files found there, including the directory itself,
+ * otherwise we just label the file.
+ */
+static int
+_virSecuritySELinuxSetFileLabels(virSecurityManagerPtr mgr,
+ const char *path,
+ virSecurityLabelDefPtr seclabel)
+{
+ int ret = 0;
+ struct dirent *ent;
+ char *filename = NULL;
+ DIR *dir;
+
+ if ((ret = virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel)))
+ return ret;
+
+ if (!virFileIsDir(path))
+ return 0;
+
+ if (virDirOpen(&dir, path) < 0)
+ return -1;
+
+ while ((ret = virDirRead(dir, &ent, path)) > 0) {
+ if (ent->d_type != DT_REG)
+ continue;
+
+ if (virAsprintf(&filename, "%s/%s", path, ent->d_name) < 0) {
+ ret = -1;
+ break;
+ }
+ ret = virSecuritySELinuxSetFilecon(mgr, filename,
+ seclabel->imagelabel);
+ VIR_FREE(filename);
+ if (ret < 0)
+ break;
+ }
+ if (ret < 0)
+ virReportSystemError(errno, _("Unable to label files under %s"),
+ path);
+
+ virDirClose(&dir);
+
+ return ret;
+}
+
+
+/*
+ * _virSecuritySELinuxRestoreFileLabels:
+ *
+ * @mgr: the virSecurityManager
+ * @path: path to a directory or a file
+ *
+ * Restore the file labels on the given path; if the path is a directory
+ * we restore all file labels found there, including the label of the
+ * directory itself, otherwise we just restore the label on the file.
+ */
+static int
+_virSecuritySELinuxRestoreFileLabels(virSecurityManagerPtr mgr,
+ const char *path)
+{
+ int ret = 0;
+ struct dirent *ent;
+ char *filename = NULL;
+ DIR *dir;
+
+ if ((ret = virSecuritySELinuxRestoreFileLabel(mgr, path)))
+ return ret;
+
+ if (!virFileIsDir(path))
+ return 0;
+
+ if (virDirOpen(&dir, path) < 0)
+ return -1;
+
+ while ((ret = virDirRead(dir, &ent, path)) > 0) {
+ if (ent->d_type != DT_REG)
+ continue;
+
+ if (virAsprintf(&filename, "%s/%s", path, ent->d_name) < 0) {
+ ret = -1;
+ break;
+ }
+ ret = virSecuritySELinuxRestoreFileLabel(mgr, filename);
+ VIR_FREE(filename);
+ if (ret < 0)
+ break;
+ }
+ if (ret < 0)
+ virReportSystemError(errno, _("Unable to restore file labels under %s"),
+ path);
+
+ virDirClose(&dir);
+
+ return ret;
+}
+
+
+static int
+virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr def)
+{
+ int ret = 0;
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+ if (seclabel == NULL)
+ return 0;
+
+ switch (def->tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ break;
+ case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ ret = _virSecuritySELinuxSetFileLabels(
+ mgr, def->tpm->data.emulator.storagepath,
+ seclabel);
+ if (ret == 0 && def->tpm->data.emulator.logfile)
+ ret = _virSecuritySELinuxSetFileLabels(
+ mgr, def->tpm->data.emulator.logfile,
+ seclabel);
+ break;
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+
+ return ret;
+}
+
+
+static int
+virSecuritySELinuxRestoreTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr def)
+{
+ int ret = 0;
+
+ switch (def->tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ break;
+ case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ ret = _virSecuritySELinuxRestoreFileLabels(
+ mgr, def->tpm->data.emulator.storagepath);
+ if (ret == 0 && def->tpm->data.emulator.logfile)
+ ret = _virSecuritySELinuxRestoreFileLabels(
+ mgr, def->tpm->data.emulator.logfile);
+ break;
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+
+ return ret;
+}
+
+
virSecurityDriver virSecurityDriverSELinux = {
.privateDataLen = sizeof(virSecuritySELinuxData),
.name = SECURITY_SELINUX_NAME,
@@ -3107,4 +3268,7 @@ virSecurityDriver virSecurityDriverSELinux = {
.domainSetSecurityChardevLabel = virSecuritySELinuxSetChardevLabel,
.domainRestoreSecurityChardevLabel = virSecuritySELinuxRestoreChardevLabel,
+
+ .domainSetSecurityTPMLabels = virSecuritySELinuxSetTPMLabels,
+ .domainRestoreSecurityTPMLabels = virSecuritySELinuxRestoreTPMLabels,
};
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
index 9615f9f..e37a681 100644
--- a/src/security/security_stack.c
+++ b/src/security/security_stack.c
@@ -760,6 +760,43 @@ virSecurityStackDomainRestoreChardevLabel(virSecurityManagerPtr mgr,
return rc;
}
+
+static int
+virSecurityStackSetTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm)
+{
+ virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ virSecurityStackItemPtr item = priv->itemsHead;
+ int rc = 0;
+
+ for (; item; item = item->next) {
+ if (virSecurityManagerSetTPMLabels(item->securityManager,
+ vm) < 0)
+ rc = -1;
+ }
+
+ return rc;
+}
+
+
+static int
+virSecurityStackRestoreTPMLabels(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm)
+{
+ virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ virSecurityStackItemPtr item = priv->itemsHead;
+ int rc = 0;
+
+ for (; item; item = item->next) {
+ if (virSecurityManagerRestoreTPMLabels(item->securityManager,
+ vm) < 0)
+ rc = -1;
+ }
+
+ return rc;
+}
+
+
virSecurityDriver virSecurityDriverStack = {
.privateDataLen = sizeof(virSecurityStackData),
.name = "stack",
@@ -822,4 +859,7 @@ virSecurityDriver virSecurityDriverStack = {
.domainSetSecurityChardevLabel = virSecurityStackDomainSetChardevLabel,
.domainRestoreSecurityChardevLabel = virSecurityStackDomainRestoreChardevLabel,
+
+ .domainSetSecurityTPMLabels = virSecurityStackSetTPMLabels,
+ .domainRestoreSecurityTPMLabels = virSecurityStackRestoreTPMLabels,
};