[libvirt] [PATCH] qemu: Copy SELinux labels for namespace too

Michal Privoznik mprivozn at redhat.com
Fri Jan 13 10:12:43 UTC 2017


When creating new /dev/* for qemu, we do chown() and copy ACLs to
create the exact copy from the original /dev. I though that
copying SELinux labels is not necessary as SELinux will chose the
sane defaults. Surprisingly, it does not leaving namespace with
the following labels:

crw-rw-rw-. root root system_u:object_r:tmpfs_t:s0     random
crw-------. root root system_u:object_r:tmpfs_t:s0     rtc0
drwxrwxrwt. root root system_u:object_r:tmpfs_t:s0     shm
crw-rw-rw-. root root system_u:object_r:tmpfs_t:s0     urandom

As a result, domain is unable to start:

error: internal error: process exited while connecting to monitor: Error in GnuTLS initialization: Failed to acquire random data.
qemu-kvm: cannot initialize crypto: Unable to initialize GNUTLS library: Failed to acquire random data.

The solution is to copy the SELinux labels as well.

Reported-by: Andrea Bolognani <abologna at redhat.com>
Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_domain.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 1399dee0d..a29866673 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -63,6 +63,9 @@
 #if defined(HAVE_SYS_MOUNT_H)
 # include <sys/mount.h>
 #endif
+#ifdef WITH_SELINUX
+# include <selinux/selinux.h>
+#endif
 
 #include <libxml/xpathInternals.h>
 
@@ -6958,6 +6961,9 @@ qemuDomainCreateDevice(const char *device,
     char *canonDevicePath = NULL;
     struct stat sb;
     int ret = -1;
+#ifdef WITH_SELINUX
+    char *tcon = NULL;
+#endif
 
     if (virFileResolveAllLinks(device, &canonDevicePath) < 0) {
         if (errno == ENOENT && allow_noent) {
@@ -7023,10 +7029,34 @@ qemuDomainCreateDevice(const char *device,
         goto cleanup;
     }
 
+#ifdef WITH_SELINUX
+    if (getfilecon_raw(canonDevicePath, &tcon) < 0 &&
+        (errno != ENOTSUP && errno != ENODATA)) {
+        virReportSystemError(errno,
+                             _("Unable to get SELinux label on %s"), canonDevicePath);
+        goto cleanup;
+    }
+
+    if (tcon &&
+        setfilecon_raw(devicePath, (VIR_SELINUX_CTX_CONST char *) tcon) < 0) {
+        VIR_WARNINGS_NO_WLOGICALOP_EQUAL_EXPR
+        if (errno != EOPNOTSUPP && errno != ENOTSUP) {
+        VIR_WARNINGS_RESET
+            virReportSystemError(errno,
+                                 _("Unable to set SELinux label on %s"),
+                                 devicePath);
+            goto cleanup;
+        }
+    }
+#endif
+
     ret = 0;
  cleanup:
     VIR_FREE(canonDevicePath);
     VIR_FREE(devicePath);
+#ifdef WITH_SELINUX
+    freecon(tcon);
+#endif
     return ret;
 }
 
@@ -7472,6 +7502,9 @@ struct qemuDomainAttachDeviceMknodData {
     const char *file;
     struct stat sb;
     void *acl;
+#ifdef WITH_SELINUX
+    char *tcon;
+#endif
 };
 
 
@@ -7515,6 +7548,19 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
         goto cleanup;
     }
 
+#ifdef WITH_SELINUX
+    if (setfilecon_raw(data->file, (VIR_SELINUX_CTX_CONST char *) data->tcon) < 0) {
+        VIR_WARNINGS_NO_WLOGICALOP_EQUAL_EXPR
+        if (errno != EOPNOTSUPP && errno != ENOTSUP) {
+        VIR_WARNINGS_RESET
+            virReportSystemError(errno,
+                                 _("Unable to set SELinux label on %s"),
+                                 data->file);
+            goto cleanup;
+        }
+    }
+#endif
+
     switch ((virDomainDeviceType) data->devDef->type) {
     case VIR_DOMAIN_DEVICE_DISK: {
         virDomainDiskDefPtr def = data->devDef->data.disk;
@@ -7571,6 +7617,9 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
  cleanup:
     if (ret < 0 && delDevice)
         unlink(data->file);
+#ifdef WITH_SELINUX
+    freecon(data->tcon);
+#endif
     virFileFreeACLs(&data->acl);
     return ret;
 }
@@ -7605,6 +7654,15 @@ qemuDomainAttachDeviceMknod(virQEMUDriverPtr driver,
         return ret;
     }
 
+#ifdef WITH_SELINUX
+    if (getfilecon_raw(file, &data.tcon) < 0 &&
+        (errno != ENOTSUP && errno != ENODATA)) {
+        virReportSystemError(errno,
+                             _("Unable to get SELinux label on %s"), file);
+        goto cleanup;
+    }
+#endif
+
     if (virSecurityManagerPreFork(driver->securityManager) < 0)
         goto cleanup;
 
@@ -7619,6 +7677,9 @@ qemuDomainAttachDeviceMknod(virQEMUDriverPtr driver,
 
     ret = 0;
  cleanup:
+#ifdef WITH_SELINUX
+    freecon(data.tcon);
+#endif
     virFileFreeACLs(&data.acl);
     return 0;
 }
-- 
2.11.0




More information about the libvir-list mailing list