c1c534
From f0e402ae3edf7717f1f2c1317f8b445ad20fdda4 Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <f0e402ae3edf7717f1f2c1317f8b445ad20fdda4@dist-git>
c1c534
From: Pavel Hrdina <phrdina@redhat.com>
c1c534
Date: Tue, 5 Dec 2017 14:02:34 +0100
c1c534
Subject: [PATCH] qemu: fix security labeling for attach/detach of char devices
c1c534
c1c534
Commit e93d844b90 was not enough to fix the permission denied
c1c534
issue.  We need to apply security labels as well.
c1c534
c1c534
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1465833
c1c534
c1c534
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c1c534
(cherry picked from commit 1c57eea3625f59a80bea08d8779837a40acc4660)
c1c534
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c1c534
Reviewed-by: Erik Skultety <eskultet@redhat.com>
c1c534
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c1c534
---
c1c534
 src/qemu/qemu_hotplug.c  | 10 ++++++++
c1c534
 src/qemu/qemu_security.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
c1c534
 src/qemu/qemu_security.h |  8 +++++++
c1c534
 3 files changed, 78 insertions(+)
c1c534
c1c534
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
c1c534
index 56e8a93885..eab9ad794a 100644
c1c534
--- a/src/qemu/qemu_hotplug.c
c1c534
+++ b/src/qemu/qemu_hotplug.c
c1c534
@@ -1818,6 +1818,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
c1c534
     bool chardevAttached = false;
c1c534
     bool teardowncgroup = false;
c1c534
     bool teardowndevice = false;
c1c534
+    bool teardownlabel = false;
c1c534
     char *tlsAlias = NULL;
c1c534
     char *secAlias = NULL;
c1c534
     bool need_release = false;
c1c534
@@ -1838,6 +1839,10 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
c1c534
         goto cleanup;
c1c534
     teardowndevice = true;
c1c534
 
c1c534
+    if (qemuSecuritySetChardevLabel(driver, vm, chr) < 0)
c1c534
+        goto cleanup;
c1c534
+    teardownlabel = true;
c1c534
+
c1c534
     if (qemuSetupChardevCgroup(vm, chr) < 0)
c1c534
         goto cleanup;
c1c534
     teardowncgroup = true;
c1c534
@@ -1880,6 +1885,8 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
c1c534
             qemuDomainReleaseDeviceAddress(vm, &chr->info, NULL);
c1c534
         if (teardowncgroup && qemuTeardownChardevCgroup(vm, chr) < 0)
c1c534
             VIR_WARN("Unable to remove chr device cgroup ACL on hotplug fail");
c1c534
+        if (teardownlabel && qemuSecurityRestoreChardevLabel(driver, vm, chr) < 0)
c1c534
+            VIR_WARN("Unable to restore security label on char device");
c1c534
         if (teardowndevice && qemuDomainNamespaceTeardownChardev(driver, vm, chr) < 0)
c1c534
             VIR_WARN("Unable to remove chr device from /dev");
c1c534
     }
c1c534
@@ -4111,6 +4118,9 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
c1c534
     if (qemuTeardownChardevCgroup(vm, chr) < 0)
c1c534
         VIR_WARN("Failed to remove chr device cgroup ACL");
c1c534
 
c1c534
+    if (qemuSecurityRestoreChardevLabel(driver, vm, chr) < 0)
c1c534
+        VIR_WARN("Unable to restore security label on char device");
c1c534
+
c1c534
     if (qemuDomainNamespaceTeardownChardev(driver, vm, chr) < 0)
c1c534
         VIR_WARN("Unable to remove chr device from /dev");
c1c534
 
c1c534
diff --git a/src/qemu/qemu_security.c b/src/qemu/qemu_security.c
c1c534
index e7d2bbd5a3..2aced22d2d 100644
c1c534
--- a/src/qemu/qemu_security.c
c1c534
+++ b/src/qemu/qemu_security.c
c1c534
@@ -364,3 +364,63 @@ qemuSecurityRestoreInputLabel(virDomainObjPtr vm,
c1c534
     virSecurityManagerTransactionAbort(driver->securityManager);
c1c534
     return ret;
c1c534
 }
c1c534
+
c1c534
+
c1c534
+int
c1c534
+qemuSecuritySetChardevLabel(virQEMUDriverPtr driver,
c1c534
+                            virDomainObjPtr vm,
c1c534
+                            virDomainChrDefPtr chr)
c1c534
+{
c1c534
+    int ret = -1;
c1c534
+    qemuDomainObjPrivatePtr priv = vm->privateData;
c1c534
+
c1c534
+    if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT) &&
c1c534
+        virSecurityManagerTransactionStart(driver->securityManager) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+    if (virSecurityManagerSetChardevLabel(driver->securityManager,
c1c534
+                                          vm->def,
c1c534
+                                          chr->source,
c1c534
+                                          priv->chardevStdioLogd) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+    if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT) &&
c1c534
+        virSecurityManagerTransactionCommit(driver->securityManager,
c1c534
+                                            vm->pid) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+    ret = 0;
c1c534
+ cleanup:
c1c534
+    virSecurityManagerTransactionAbort(driver->securityManager);
c1c534
+    return ret;
c1c534
+}
c1c534
+
c1c534
+
c1c534
+int
c1c534
+qemuSecurityRestoreChardevLabel(virQEMUDriverPtr driver,
c1c534
+                                virDomainObjPtr vm,
c1c534
+                                virDomainChrDefPtr chr)
c1c534
+{
c1c534
+    int ret = -1;
c1c534
+    qemuDomainObjPrivatePtr priv = vm->privateData;
c1c534
+
c1c534
+    if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT) &&
c1c534
+        virSecurityManagerTransactionStart(driver->securityManager) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+    if (virSecurityManagerRestoreChardevLabel(driver->securityManager,
c1c534
+                                              vm->def,
c1c534
+                                              chr->source,
c1c534
+                                              priv->chardevStdioLogd) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+    if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT) &&
c1c534
+        virSecurityManagerTransactionCommit(driver->securityManager,
c1c534
+                                            vm->pid) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+    ret = 0;
c1c534
+ cleanup:
c1c534
+    virSecurityManagerTransactionAbort(driver->securityManager);
c1c534
+    return ret;
c1c534
+}
c1c534
diff --git a/src/qemu/qemu_security.h b/src/qemu/qemu_security.h
c1c534
index 76d63f06ec..d54ce6fead 100644
c1c534
--- a/src/qemu/qemu_security.h
c1c534
+++ b/src/qemu/qemu_security.h
c1c534
@@ -76,6 +76,14 @@ int qemuSecuritySetInputLabel(virDomainObjPtr vm,
c1c534
 int qemuSecurityRestoreInputLabel(virDomainObjPtr vm,
c1c534
                                   virDomainInputDefPtr input);
c1c534
 
c1c534
+int qemuSecuritySetChardevLabel(virQEMUDriverPtr driver,
c1c534
+                                virDomainObjPtr vm,
c1c534
+                                virDomainChrDefPtr chr);
c1c534
+
c1c534
+int qemuSecurityRestoreChardevLabel(virQEMUDriverPtr driver,
c1c534
+                                    virDomainObjPtr vm,
c1c534
+                                    virDomainChrDefPtr chr);
c1c534
+
c1c534
 /* Please note that for these APIs there is no wrapper yet. Do NOT blindly add
c1c534
  * new APIs here. If an API can touch a /dev file add a proper wrapper instead.
c1c534
  */
c1c534
-- 
c1c534
2.15.1
c1c534