render / rpms / libvirt

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