aff97e
From 3c75dc1ed9a32fff16c84f60536ee21ff8e9e19f Mon Sep 17 00:00:00 2001
3ec523
From: Michal Privoznik <mprivozn@redhat.com>
3ec523
Date: Thu, 18 Sep 2014 15:17:29 +0200
3ec523
Subject: [PATCH] virSecuritySELinuxSetTapFDLabel: Temporarily revert to old
3ec523
 behavior
3ec523
3ec523
https://bugzilla.redhat.com/show_bug.cgi?id=1141879
3ec523
3ec523
A long time ago I've implemented support for so called multiqueue
3ec523
net.  The idea was to let guest network traffic be processed by
3ec523
multiple host CPUs and thus increasing performance. However, this
3ec523
behavior is enabled by QEMU via special ioctl() iterated over the
3ec523
all tap FDs passed in by libvirt. Unfortunately, SELinux comes in
3ec523
and disallows the ioctl() call because the /dev/net/tun has label
3ec523
system_u:object_r:tun_tap_device_t:s0 and 'attach_queue' ioctl()
3ec523
is not allowed on tun_tap_device_t type. So after discussion with
3ec523
a SELinux developer we've decided that the FDs passed to the QEMU
3ec523
should be labelled with svirt_t type and SELinux policy will
3ec523
allow the ioctl(). Therefore I've made a patch
3ec523
(cf976d9dcf4e592261b14f03572) that does exactly this. The patch
3ec523
was fixed then by a4431931393aeb1ac5893f121151fa3df4fde612 and
3ec523
b635b7a1af0e64754016d758376f382470bc11e7. However, things are not
3ec523
that easy - even though the API to label FD is called
3ec523
(fsetfilecon_raw) the underlying file is labelled too! So
3ec523
effectively we are mangling /dev/net/tun label. Yes, that broke
3ec523
dozen of other application from openvpn, or boxes, to qemu
3ec523
running other domains.
3ec523
3ec523
The best solution would be if SELinux provides a way to label an
3ec523
FD only, which could be then labeled when passed to the qemu.
3ec523
However that's a long path to go and we should fix this
3ec523
regression AQAP. So I went to talk to the SELinux developer again
3ec523
and we agreed on temporary solution that:
3ec523
3ec523
1) All the three patches are reverted
3ec523
2) SELinux temporarily allows 'attach_queue' on the
3ec523
tun_tap_device_t
3ec523
3ec523
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
3ec523
(cherry picked from commit ba7468dbb13f552a9177d01ea8bad155f9877bc3)
3ec523
---
3ec523
 src/security/security_selinux.c | 34 ++++++++++++++++++++++++++++++++--
3ec523
 1 file changed, 32 insertions(+), 2 deletions(-)
3ec523
3ec523
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
3ec523
index e8c13db..c078cab 100644
3ec523
--- a/src/security/security_selinux.c
3ec523
+++ b/src/security/security_selinux.c
3ec523
@@ -2330,17 +2330,47 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
3ec523
 }
3ec523
 
3ec523
 static int
3ec523
-virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
3ec523
+virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
3ec523
                                 virDomainDefPtr def,
3ec523
                                 int fd)
3ec523
 {
3ec523
+    struct stat buf;
3ec523
+    security_context_t fcon = NULL;
3ec523
     virSecurityLabelDefPtr secdef;
3ec523
+    char *str = NULL;
3ec523
+    int rc = -1;
3ec523
 
3ec523
     secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
3ec523
     if (!secdef || !secdef->label)
3ec523
         return 0;
3ec523
 
3ec523
-    return virSecuritySELinuxFSetFilecon(fd, secdef->imagelabel);
3ec523
+    if (fstat(fd, &buf) < 0) {
3ec523
+        virReportSystemError(errno, _("cannot stat tap fd %d"), fd);
3ec523
+        goto cleanup;
3ec523
+    }
3ec523
+
3ec523
+    if ((buf.st_mode & S_IFMT) != S_IFCHR) {
3ec523
+        virReportError(VIR_ERR_INTERNAL_ERROR,
3ec523
+                       _("tap fd %d is not character device"), fd);
3ec523
+        goto cleanup;
3ec523
+    }
3ec523
+
3ec523
+    if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) {
3ec523
+        virReportError(VIR_ERR_INTERNAL_ERROR,
3ec523
+                       _("cannot lookup default selinux label for tap fd %d"), fd);
3ec523
+        goto cleanup;
3ec523
+    }
3ec523
+
3ec523
+    if (!(str = virSecuritySELinuxContextAddRange(secdef->label, fcon))) {
3ec523
+        goto cleanup;
3ec523
+    } else {
3ec523
+        rc = virSecuritySELinuxFSetFilecon(fd, str);
3ec523
+    }
3ec523
+
3ec523
+ cleanup:
3ec523
+    freecon(fcon);
3ec523
+    VIR_FREE(str);
3ec523
+    return rc;
3ec523
 }
3ec523
 
3ec523
 static char *