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