render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
9119d9
From 03a842c7997b0e299a6b044f4822024e9be2bc7d Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <03a842c7997b0e299a6b044f4822024e9be2bc7d@dist-git>
9119d9
From: Michal Privoznik <mprivozn@redhat.com>
9119d9
Date: Wed, 15 Oct 2014 12:55:00 +0200
9119d9
Subject: [PATCH] security_selinux: Don't relabel /dev/net/tun
9119d9
9119d9
RHEL-7: https://bugzilla.redhat.com/show_bug.cgi?id=1095636
9119d9
Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1147057
9119d9
9119d9
The code for relabelling the TAP FD is there due to a race. When
9119d9
libvirt creates a /dev/tapN device it's labeled as
9119d9
'system_u:object_r:device_t:s0' by default. Later, when
9119d9
udev/systemd reacts to this device, it's relabelled to the
9119d9
expected label 'system_u:object_r:tun_tap_device_t:s0'. Hence, we
9119d9
have a code that relabels the device, to cut the race down. For
9119d9
more info see ae368ebfcc4.
9119d9
9119d9
But the problem is, the relabel function is called on all TUN/TAP
9119d9
devices. Yes, on /dev/net/tun too. This is however a special kind
9119d9
of device - other processes uses it too. We shouldn't touch it's
9119d9
label then.
9119d9
9119d9
Ideally, there would an API in SELinux that would label just the
9119d9
passed FD and not the underlying path. That way, we wouldn't need
9119d9
to care as we would be not labeling /dev/net/tun but the FD
9119d9
passed to the domain. Unfortunately, there's no such API so we
9119d9
have to workaround until then.
9119d9
9119d9
Tested-by: Richard W.M. Jones <rjones@redhat.com>
9119d9
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
9119d9
(cherry picked from commit ebc05263960f41065fa7d882959ea754b9281ab1)
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/security/security_selinux.c | 23 +++++++++++++++++++++--
9119d9
 1 file changed, 21 insertions(+), 2 deletions(-)
9119d9
9119d9
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
9119d9
index b7c1015..352f1ab 100644
9119d9
--- a/src/security/security_selinux.c
9119d9
+++ b/src/security/security_selinux.c
9119d9
@@ -2352,7 +2352,7 @@ virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
9119d9
     struct stat buf;
9119d9
     security_context_t fcon = NULL;
9119d9
     virSecurityLabelDefPtr secdef;
9119d9
-    char *str = NULL;
9119d9
+    char *str = NULL, *proc = NULL, *fd_path = NULL;
9119d9
     int rc = -1;
9119d9
 
9119d9
     secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
9119d9
@@ -2370,7 +2370,24 @@ virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
9119d9
         goto cleanup;
9119d9
     }
9119d9
 
9119d9
-    if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) {
9119d9
+    /* Label /dev/tap.* devices only. Leave /dev/net/tun alone! */
9119d9
+    if (virAsprintf(&proc, "/proc/self/fd/%d", fd) == -1)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (virFileResolveLink(proc, &fd_path) < 0) {
9119d9
+        virReportSystemError(errno,
9119d9
+                             _("Unable to resolve link: %s"), proc);
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    if (!STRPREFIX(fd_path, "/dev/tap")) {
9119d9
+        VIR_DEBUG("fd=%d points to %s not setting SELinux label",
9119d9
+                  fd, fd_path);
9119d9
+        rc = 0;
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
@@ -2384,6 +2401,8 @@ virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
9119d9
 
9119d9
  cleanup:
9119d9
     freecon(fcon);
9119d9
+    VIR_FREE(fd_path);
9119d9
+    VIR_FREE(proc);
9119d9
     VIR_FREE(str);
9119d9
     return rc;
9119d9
 }
9119d9
-- 
9119d9
2.1.3
9119d9