[libvirt] [PATCH] Support custom 'svirt_tcg_t' context for TCG based guests

Daniel P. Berrange berrange at redhat.com
Wed Dec 12 11:49:19 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

The current SELinux policy only works for KVM guests, since
TCG requires the 'execmem' privilege. There is a 'virt_use_execmem'
boolean to turn this on globally, but that is unpleasant for users.
This changes libvirt to automatically use a new 'svirt_tcg_t'
context for TCG based guests. This obsoletes the previous
boolean tunable and makes things 'just work(tm)'

Since we can't assume we run with new enough policy, I also
make us log a warning message (once only) if we find the policy
lacks support. In this case we fallback to the normal label and
expect users to set the boolean tunable

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/security/security_selinux.c | 48 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 5409e32..82cbc80 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -58,6 +58,7 @@ typedef virSecuritySELinuxCallbackData *virSecuritySELinuxCallbackDataPtr;
 
 struct _virSecuritySELinuxData {
     char *domain_context;
+    char *alt_domain_context;
     char *file_context;
     char *content_context;
     virHashTablePtr mcs;
@@ -446,8 +447,23 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr)
     }
 
     ptr = strchrnul(data->domain_context, '\n');
-    if (ptr)
+    if (ptr && *ptr == '\n') {
         *ptr = '\0';
+        ptr++;
+        if (*ptr != '\0') {
+            data->alt_domain_context = strdup(ptr);
+            if (!data->alt_domain_context) {
+                virReportOOMError();
+                goto error;
+            }
+            ptr = strchrnul(data->alt_domain_context, '\n');
+            if (ptr && *ptr == '\n')
+                *ptr = '\0';
+        }
+    }
+    VIR_DEBUG("Loaded domain context '%s', alt domain context '%s'",
+              data->domain_context, NULLSTR(data->alt_domain_context));
+
 
     if (virFileReadAll(selinux_virtual_image_context_path(), 2*MAX_CONTEXT, &(data->file_context)) < 0) {
         virReportSystemError(errno,
@@ -469,6 +485,9 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr)
             *ptr = '\0';
     }
 
+    VIR_DEBUG("Loaded file context '%s', content context '%s'",
+              data->file_context, data->content_context);
+
     if (!(data->mcs = virHashCreate(10, NULL)))
         goto error;
 
@@ -476,6 +495,7 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr)
 
 error:
     VIR_FREE(data->domain_context);
+    VIR_FREE(data->alt_domain_context);
     VIR_FREE(data->file_context);
     VIR_FREE(data->content_context);
     virHashFree(data->mcs);
@@ -506,6 +526,7 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
     const char *range;
     virSecurityLabelDefPtr seclabel;
     virSecuritySELinuxDataPtr data;
+    const char *baselabel;
 
     if (mgr == NULL) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -568,10 +589,28 @@ virSecuritySELinuxGenSecurityLabel(virSecurityManagerPtr mgr,
         if (virSecuritySELinuxMCSAdd(mgr, mcs) < 0)
             goto cleanup;
 
+        baselabel = seclabel->baselabel;
+        if (!baselabel) {
+            if (def->virtType == VIR_DOMAIN_VIRT_QEMU) {
+                if (data->alt_domain_context == NULL) {
+                    static bool warned = false;
+                    if (!warned) {
+                        VIR_WARN("SELinux policy does not define a domain type for QEMU TCG. "
+                                 "Guest startup may be denied due to missing 'execmem' privilege "
+                                 "unless the 'virt_use_execmem' policy boolean is enabled");
+                        warned = true;
+                    }
+                    baselabel = data->domain_context;
+                } else {
+                    baselabel = data->alt_domain_context;
+                }
+            } else {
+                baselabel = data->domain_context;
+            }
+        }
+
         seclabel->label =
-            virSecuritySELinuxGenNewContext(seclabel->baselabel ?
-                                 seclabel->baselabel :
-                                 data->domain_context, mcs, false);
+            virSecuritySELinuxGenNewContext(baselabel, mcs, false);
         if (!seclabel->label)  {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot generate selinux context for %s"), mcs);
@@ -722,6 +761,7 @@ virSecuritySELinuxSecurityDriverClose(virSecurityManagerPtr mgr)
     virHashFree(data->mcs);
 
     VIR_FREE(data->domain_context);
+    VIR_FREE(data->alt_domain_context);
     VIR_FREE(data->file_context);
     VIR_FREE(data->content_context);
 
-- 
1.7.11.7




More information about the libvir-list mailing list