In this patch we label the swtpm process with SELinux labels. We give it the
same label as the QEMU process has. We label its state directory and files
as well.

The file and process labels now look as follows:

[root@localhost tpm]# ls -lZ
total 4
rwx------. 2 tss  tss  system_u:object_r:svirt_image_t:s0:c254,c932 4096 Apr  5 
16:46 485d0004-a48f-436a-8457-8a3b73e28567
srw-------. 1 qemu qemu system_u:object_r:svirt_image_t:s0:c254,c932    0 Apr  
5 16:57 485d0004-a48f-436a-8457-8a3b73e28567.sock

[root@localhost 485d0004-a48f-436a-8457-8a3b73e28567]# ls -lZ
total 8
-rw-r--r--. 1 tss tss system_u:object_r:svirt_image_t:s0:c254,c932 3648 Apr  5 
16:46 tpm-00.permall
-rw-r--r--. 1 tss tss system_u:object_r:svirt_image_t:s0:c254,c932 2237 Apr  5 
16:46 vtpm.log

root@sbct-3 485d0004-a48f-436a-8457-8a3b73e28567]# ps auxZ | grep swtpm | grep 
-v grep
system_u:system_r:svirt_t:s0:c254,c932 tss 25664 0.0  0.0 28172  3892 ?        
Ss   16:57   0:00 /usr/bin/swtpm socket --daemon --ctrl 
type=unixio,path=/var/lib/libvirt/tpm/485d0004-a48f-436a-8457-8a3b73e28567.sock,mode=0600
 --tpmstate dir=/var/lib/libvirt/tpm/485d0004-a48f-436a-8457-8a3b73e28567 --log 
file=/var/lib/libvirt/tpm/485d0004-a48f-436a-8457-8a3b73e28567/vtpm.log --runas 
59

[root@sbct-3 485d0004-a48f-436a-8457-8a3b73e28567]# ps auxZ | grep qemu | grep 
tpm | grep -v grep
system_u:system_r:svirt_t:s0:c254,c932 qemu 25669 99.0  0.0 3096704 48500 ?    
Sl   16:57   3:28 /bin/qemu-system-x86_64 -name 
guest=centos7.0,debug-threads=on -S -object 
secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-centos7.0/master-key.aes
 -machine pc-i440fx-2.8,accel=kvm,usb=off,dump-guest-core=off -cpu kvm64 -m 
2048 -realtime mlock=off -smp 2,sockets=2,cores=1,threads=1 -uuid 
485d0004-a48f-436a-8457-8a3b73e28567 [...] -tpmdev 
emulator,id=tpm-tpm0,chardev=chrtpm -chardev 
socket,id=chrtpm,path=/var/lib/libvirt/tpm/485d0004-a48f-436a-8457-8a3b73e28567.sock
 -device tpm-tis,tpmdev=tpm-tpm0,id=tpm0 -device 
usb-mouse,id=input0,bus=usb.0,port=1 -vnc 127.0.0.1:0 -device 
cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device 
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 -msg timestamp=on

Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com>
---
 src/conf/domain_conf.c          |  2 +
 src/conf/domain_conf.h          |  3 ++
 src/libvirt_private.syms        |  1 +
 src/qemu/qemu_extdevice.c       | 26 +++++++++++-
 src/security/security_driver.h  |  5 ++-
 src/security/security_manager.c | 15 +++++++
 src/security/security_manager.h |  3 ++
 src/security/security_selinux.c | 90 +++++++++++++++++++++++++++++++++++++++++
 src/security/security_stack.c   | 19 +++++++++
 src/util/virtpm.c               |  5 ++-
 10 files changed, 165 insertions(+), 4 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index da14ef8..9f7f3ce 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2623,6 +2623,8 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def)
         break;
     case VIR_DOMAIN_TPM_TYPE_EMULATOR:
         VIR_FREE(def->data.emulator.source.data.nix.path);
+        VIR_FREE(def->data.emulator.storagepath);
+        VIR_FREE(def->data.emulator.logfile);
         break;
     case VIR_DOMAIN_TPM_TYPE_LAST:
         break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4ecc70d..9802533 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1301,6 +1301,9 @@ struct _virDomainTPMDef {
         } passthrough;
         struct {
             virDomainChrSourceDef source;
+            /* swtpm storage path and logfile */
+            char *storagepath;
+            char *logfile;
         } emulator;
     } data;
 };
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e64bbef..191142e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1334,6 +1334,7 @@ virSecurityManagerSetProcessLabel;
 virSecurityManagerSetSavedStateLabel;
 virSecurityManagerSetSocketLabel;
 virSecurityManagerSetTapFDLabel;
+virSecurityManagerSetTPMLabels;
 virSecurityManagerStackAddNested;
 virSecurityManagerTransactionAbort;
 virSecurityManagerTransactionCommit;
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 4f42c9b..e685faf 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -105,12 +105,36 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
 
     virCommandSetErrorBuffer(cmd, &errbuf);
 
-    if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
+    if (virSecurityManagerSetTPMLabels(driver->securityManager,
+                                       def) < 0)
+        goto error;
+
+    if (virSecurityManagerSetChildProcessLabel(driver->securityManager,
+                                               def, cmd) < 0)
+        goto error;
+
+    if (virSecurityManagerPreFork(driver->securityManager) < 0)
+        goto error;
+
+    /*
+     * make sure we run this as root
+     * note: when installing libvirtd via make install we don't need this,
+     *       but when installed from RPM, this is necessary.
+     */
+    virCommandSetUID(cmd, 0);
+    virCommandSetGID(cmd, 0);
+
+    ret = virCommandRun(cmd, &exitstatus);
+
+    virSecurityManagerPostFork(driver->securityManager);
+
+    if (ret < 0 || exitstatus != 0) {
         VIR_ERROR("Could not start 'swtpm'. exitstatus: %d\n"
                   "stderr: %s\n", exitstatus, errbuf);
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Could not start 'swtpm'. exitstatus: %d, "
                        "error: %s"), exitstatus, errbuf);
+        ret = -1;
         goto error;
     }
 
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index 95e7c4d..c654d2b 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -149,7 +149,8 @@ typedef int (*virSecurityDomainRestoreChardevLabel) 
(virSecurityManagerPtr mgr,
                                                      virDomainDefPtr def,
                                                      virDomainChrSourceDefPtr 
dev_source,
                                                      bool chardevStdioLogd);
-
+typedef int (*virSecurityDomainSetTPMLabels) (virSecurityManagerPtr mgr,
+                                              virDomainDefPtr def);
 
 struct _virSecurityDriver {
     size_t privateDataLen;
@@ -213,6 +214,8 @@ struct _virSecurityDriver {
 
     virSecurityDomainSetChardevLabel domainSetSecurityChardevLabel;
     virSecurityDomainRestoreChardevLabel domainRestoreSecurityChardevLabel;
+
+    virSecurityDomainSetTPMLabels domainSetSecurityTPMLabels;
 };
 
 virSecurityDriverPtr virSecurityDriverLookup(const char *name,
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index fdeea4d..7ff9050 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -1207,3 +1207,18 @@ 
virSecurityManagerRestoreChardevLabel(virSecurityManagerPtr mgr,
     virReportUnsupportedError();
     return -1;
 }
+
+
+int virSecurityManagerSetTPMLabels(virSecurityManagerPtr mgr,
+                                   virDomainDefPtr vm)
+{
+    if (mgr->drv->domainSetSecurityTPMLabels) {
+        int ret;
+        virObjectLock(mgr);
+        ret = mgr->drv->domainSetSecurityTPMLabels(mgr, vm);
+        virObjectUnlock(mgr);
+        return ret;
+    }
+
+    return 0;
+}
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index c36a8b4..671f6a8 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -194,4 +194,7 @@ int 
virSecurityManagerRestoreChardevLabel(virSecurityManagerPtr mgr,
                                           virDomainChrSourceDefPtr dev_source,
                                           bool chardevStdioLogd);
 
+int virSecurityManagerSetTPMLabels(virSecurityManagerPtr mgr,
+                                   virDomainDefPtr vm);
+
 #endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index cfc8311..7bc1786 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -30,6 +30,7 @@
 #if HAVE_SELINUX_LABEL_H
 # include <selinux/label.h>
 #endif
+#include <dirent.h>
 
 #include "security_driver.h"
 #include "security_selinux.h"
@@ -3051,6 +3052,93 @@ 
virSecuritySELinuxDomainSetPathLabel(virSecurityManagerPtr mgr,
     return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel);
 }
 
+static int
+_virSecuritySELinuxSetSecurityFileLabels(virSecurityManagerPtr mgr,
+                                         const char *path,
+                                         virSecurityLabelDefPtr seclabel,
+                                         bool recurse)
+{
+    int ret = 0;
+    int n = 0;
+    struct dirent dirent, *result = NULL;
+    struct stat stat;
+    char *filename = NULL;
+    DIR *dir = opendir(path);
+
+    if (!dir)
+        return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel);
+
+    while ((n = readdir_r(dir, &dirent, &result)) == 0) {
+        if (result == NULL)
+            break;
+        /* do NOT step into parent dir */
+        if (STREQ("..", dirent.d_name))
+            continue;
+        if (virAsprintf(&filename, "%s/%s", path, dirent.d_name) < 0) {
+            ret = -1;
+            break;
+        }
+        n = lstat(filename, &stat);
+        if (n != 0)
+            break;
+        if (S_ISDIR(stat.st_mode)) {
+            ret = virSecuritySELinuxSetFilecon(mgr, filename, 
seclabel->imagelabel);
+            if (ret)
+                break;
+            if (recurse)
+                ret = _virSecuritySELinuxSetSecurityFileLabels(mgr, filename,
+                                                               seclabel,
+                                                               recurse);
+        } else if (S_ISREG(stat.st_mode)) {
+            ret = virSecuritySELinuxSetFilecon(mgr, filename,
+                                               seclabel->imagelabel);
+        }
+        VIR_FREE(filename);
+        if (ret)
+            break;
+    }
+    if (n) {
+        virReportSystemError(errno, _("Unable to label files under %s"),
+                             path);
+        ret = -1;
+    }
+
+    VIR_FREE(filename);
+    closedir(dir);
+
+    return ret;
+}
+
+static int
+virSecuritySELinuxSetSecurityTPMLabels(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 = _virSecuritySELinuxSetSecurityFileLabels(
+            mgr, def->tpm->data.emulator.storagepath,
+            seclabel, false);
+        if (ret == 0 && def->tpm->data.emulator.logfile)
+            ret = _virSecuritySELinuxSetSecurityFileLabels(
+                mgr, def->tpm->data.emulator.logfile,
+                seclabel, false);
+        break;
+    case VIR_DOMAIN_TPM_TYPE_LAST:
+        break;
+    }
+
+    return ret;
+}
+
 virSecurityDriver virSecurityDriverSELinux = {
     .privateDataLen                     = sizeof(virSecuritySELinuxData),
     .name                               = SECURITY_SELINUX_NAME,
@@ -3110,4 +3198,6 @@ virSecurityDriver virSecurityDriverSELinux = {
 
     .domainSetSecurityChardevLabel      = virSecuritySELinuxSetChardevLabel,
     .domainRestoreSecurityChardevLabel  = 
virSecuritySELinuxRestoreChardevLabel,
+
+    .domainSetSecurityTPMLabels         = 
virSecuritySELinuxSetSecurityTPMLabels,
 };
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
index 9615f9f..7f10ef0 100644
--- a/src/security/security_stack.c
+++ b/src/security/security_stack.c
@@ -760,6 +760,23 @@ 
virSecurityStackDomainRestoreChardevLabel(virSecurityManagerPtr mgr,
     return rc;
 }
 
+static int
+virSecurityStackSetSecurityTPMLabels(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;
+}
+
 virSecurityDriver virSecurityDriverStack = {
     .privateDataLen                     = sizeof(virSecurityStackData),
     .name                               = "stack",
@@ -822,4 +839,6 @@ virSecurityDriver virSecurityDriverStack = {
 
     .domainSetSecurityChardevLabel      = 
virSecurityStackDomainSetChardevLabel,
     .domainRestoreSecurityChardevLabel  = 
virSecurityStackDomainRestoreChardevLabel,
+
+    .domainSetSecurityTPMLabels         = virSecurityStackSetSecurityTPMLabels,
 };
diff --git a/src/util/virtpm.c b/src/util/virtpm.c
index 8a99876..354761e 100644
--- a/src/util/virtpm.c
+++ b/src/util/virtpm.c
@@ -437,8 +437,9 @@ virTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, const 
unsigned char *vmuuid,
         virCommandAllowCap(cmd, CAP_SETUID);
     }
 
-    VIR_FREE(storagepath);
-    VIR_FREE(logfile);
+    tpm->data.emulator.storagepath = storagepath;
+    VIR_FREE(tpm->data.emulator.logfile);
+    tpm->data.emulator.logfile = logfile;
 
     return cmd;
 
-- 
2.5.5

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to