From: Michal Privoznik Date: Fri, 13 Jan 2017 09:03:23 +0000 (+0100) Subject: qemu: Copy SELinux labels for namespace too X-Git-Tag: v3.0.0-rc2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93a062c3b293685024d60e841a37e93e303f4943;p=thirdparty%2Flibvirt.git qemu: Copy SELinux labels for namespace too 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 Signed-off-by: Michal Privoznik --- diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1399dee0d2..35baffb510 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -63,6 +63,9 @@ #if defined(HAVE_SYS_MOUNT_H) # include #endif +#ifdef WITH_SELINUX +# include +#endif #include @@ -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,35 @@ 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 from %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 +7503,9 @@ struct qemuDomainAttachDeviceMknodData { const char *file; struct stat sb; void *acl; +#ifdef WITH_SELINUX + char *tcon; +#endif }; @@ -7515,6 +7549,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 +7618,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 +7655,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 from %s"), file); + goto cleanup; + } +#endif + if (virSecurityManagerPreFork(driver->securityManager) < 0) goto cleanup; @@ -7619,8 +7678,11 @@ qemuDomainAttachDeviceMknod(virQEMUDriverPtr driver, ret = 0; cleanup: +#ifdef WITH_SELINUX + freecon(data.tcon); +#endif virFileFreeACLs(&data.acl); - return 0; + return ret; }