This patch extends the SELinux and DAC security handlers with support
for the TPM's storage file.
If the user did not provide an explicit file for TPM data storage, then
a dummy-file is created in the drivers here and labeled. Athis is necessary
since the creation of the TPM's QCoW2 storage file happens later.
There is no code for AppArmor. I am not sure whether it needs explicit
support. Obviously I haven't tested it with AppArmor.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
---
src/security/security_dac.c | 102 ++++++++++++++++++++++++++++++++++++++++
src/security/security_selinux.c | 100 +++++++++++++++++++++++++++++++++++++++
2 files changed, 202 insertions(+)
Index: libvirt-acl/src/security/security_selinux.c
===================================================================
--- libvirt-acl.orig/src/security/security_selinux.c
+++ libvirt-acl/src/security/security_selinux.c
@@ -522,6 +522,94 @@ SELinuxRestoreSecurityImageLabel(virSecu
static int
+SELinuxSetSecurityTPMFileLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ virDomainTPMDefPtr tpm)
+{
+ int rc;
+ char *path;
+ struct stat statbuf;
+ FILE *f;
+ const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+
+ if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
+ return 0;
+
+ switch (tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_BUILTIN:
+ path = virDomainTPMGetStorageFilename(tpm,
+ vm->def->uuid);
+ if (stat(path, &statbuf) == -1 && errno == ENOENT) {
+ f = fopen(path, "w");
+ VIR_FORCE_FCLOSE(f);
+ }
+ rc = SELinuxSetFilecon(path, vm->def->seclabel.imagelabel);
+ VIR_FREE(path);
+ if (rc < 0)
+ return -1;
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+
+ return 0;
+}
+
+
+static int
+SELinuxRestoreSecurityTPMFileLabelInt(
+ virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ virDomainTPMDefPtr tpm,
+ int migrated)
+{
+ int rc = 0;
+ char *path;
+ struct stat statbuf;
+ const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+
+ if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
+ return 0;
+
+ switch (tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_BUILTIN:
+ path = virDomainTPMGetStorageFilename(tpm,
+ vm->def->uuid);
+ if (stat(path, &statbuf) == 0 && statbuf.st_size == 0)
+ unlink(path);
+
+ /* 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) {
+ rc = virStorageFileIsSharedFS(path);
+ if (rc < 0) {
+ VIR_FREE(path);
+ return -1;
+ }
+ if (rc == 1) {
+ VIR_DEBUG("Skipping image label restore on %s because FS is
shared",
+ path);
+ VIR_FREE(path);
+ return 0;
+ }
+ }
+ rc = SELinuxRestoreSecurityFileLabel(path);
+ VIR_FREE(path);
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+
+ return rc;
+}
+
+
+static int
SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
const char *path,
size_t depth,
@@ -854,6 +942,14 @@ SELinuxRestoreSecurityAllLabel(virSecuri
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
return 0;
+ if (vm->def->tpm) {
+ if (SELinuxRestoreSecurityTPMFileLabelInt(mgr,
+ vm,
+ vm->def->tpm,
+ migrated) < 0)
+ rc = -1;
+ }
+
for (i = 0 ; i < vm->def->nhostdevs ; i++) {
if (SELinuxRestoreSecurityHostdevLabel(mgr,
vm,
@@ -1171,6 +1267,10 @@ SELinuxSetSecurityAllLabel(virSecurityMa
vm->def->hostdevs[i]) < 0)
return -1;
}
+ if (vm->def->tpm)
+ if (SELinuxSetSecurityTPMFileLabel(mgr,
+ vm, vm->def->tpm) < 0)
+ return -1;
if (virDomainChrDefForeach(vm->def,
true,
Index: libvirt-acl/src/security/security_dac.c
===================================================================
--- libvirt-acl.orig/src/security/security_dac.c
+++ libvirt-acl/src/security/security_dac.c
@@ -31,6 +31,7 @@
#include "pci.h"
#include "hostusb.h"
#include "storage_file.h"
+#include "files.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -243,6 +244,94 @@ virSecurityDACRestoreSecurityImageLabel(
static int
+virSecurityDACSetSecurityTPMFileLabel(virSecurityManagerPtr mgr,
+ virDomainObjPtr vm,
+ virDomainTPMDefPtr tpm)
+{
+ int rc;
+ char *path;
+ struct stat statbuf;
+ FILE *f;
+ virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+ if (!priv->dynamicOwnership)
+ return 0;
+
+ switch (tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_BUILTIN:
+ path = virDomainTPMGetStorageFilename(tpm,
+ vm->def->uuid);
+ if (stat(path, &statbuf) == -1 && errno == ENOENT) {
+ f = fopen(path, "w");
+ VIR_FORCE_FCLOSE(f);
+ }
+ rc = virSecurityDACSetOwnership(path, priv->user, priv->group);
+ VIR_FREE(path);
+ if (rc < 0)
+ return -1;
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+
+ return 0;
+}
+
+
+static int
+virSecurityDACRestoreSecurityTPMFileLabelInt(
+ virSecurityManagerPtr mgr,
+ virDomainObjPtr vm,
+ virDomainTPMDefPtr tpm,
+ int migrated)
+{
+ int rc = 0;
+ char *path;
+ struct stat statbuf;
+ virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+ if (!priv->dynamicOwnership)
+ return 0;
+
+ switch (tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_BUILTIN:
+ path = virDomainTPMGetStorageFilename(tpm,
+ vm->def->uuid);
+ if (stat(path, &statbuf) == 0 && statbuf.st_size == 0)
+ unlink(path);
+
+ /* 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) {
+ rc = virStorageFileIsSharedFS(path);
+ if (rc < 0) {
+ VIR_FREE(path);
+ return -1;
+ }
+ if (rc == 1) {
+ VIR_DEBUG("Skipping image label restore on %s because FS is
shared",
+ path);
+ VIR_FREE(path);
+ return 0;
+ }
+ }
+ rc = virSecurityDACRestoreSecurityFileLabel(path);
+ VIR_FREE(path);
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+
+ return rc;
+}
+
+
+static int
virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
const char *file,
void *opaque)
@@ -492,6 +581,14 @@ virSecurityDACRestoreSecurityAllLabel(vi
VIR_DEBUG("Restoring security label on %s migrated=%d",
vm->def->name, migrated);
+ if (vm->def->tpm) {
+ if (virSecurityDACRestoreSecurityTPMFileLabelInt(mgr,
+ vm,
+ vm->def->tpm,
+ migrated) < 0)
+ rc = -1;
+ }
+
for (i = 0 ; i < vm->def->nhostdevs ; i++) {
if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
vm,
@@ -561,6 +658,11 @@ virSecurityDACSetSecurityAllLabel(virSec
vm->def->hostdevs[i]) < 0)
return -1;
}
+ if (vm->def->tpm)
+ if (virSecurityDACSetSecurityTPMFileLabel(mgr,
+ vm,
+ vm->def->tpm) < 0)
+ return -1;
if (virDomainChrDefForeach(vm->def,
true,