Blame SOURCES/libvirt-virSecuritySELinuxSetTapFDLabel-Temporarily-revert-to-old-behavior.patch

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