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@xxxxxxxxxx> Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list