[libvirt] [PATCH v2 1/2] Honour current sensitivity and category ranges in SELinux label generation

Daniel P. Berrange berrange at redhat.com
Tue Aug 14 14:36:04 UTC 2012


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

Currently the dynamic label generation code will create labels
with a sensitivity of s0, and a category pair in the range
0-1023. This is fine when running a standard MCS policy because
libvirtd will run with a label

  system_u:system_r:virtd_t:s0-s0:c0.c1023

With custom policies though, it is possible for libvirtd to have
a different sensitivity, or category range. For example

  system_u:system_r:virtd_t:s2-s3:c512.c1023

In this case we must assign the VM a sensitivity matching the
current lower sensitivity value, and categories in the range
512-1023

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

diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 48fd78b..bc24dca 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -106,13 +106,108 @@ virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr)
     int c1 = 0;
     int c2 = 0;
     char *mcs = NULL;
+    security_context_t ourSecContext = NULL;
+    context_t ourContext = NULL;
+    char *sens, *cat, *tmp;
+    int catMin, catMax, catRange;
+
+    if (getcon(&ourSecContext) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to get current process SELinux context"));
+        goto cleanup;
+    }
+    if (!(ourContext = context_new(ourSecContext))) {
+        virReportSystemError(errno,
+                             _("Unable to parse current SELinux context '%s'"),
+                             ourSecContext);
+        goto cleanup;
+    }
+
+    if (!(sens = strdup(context_range_get(ourContext)))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    /* Find and blank out the category part */
+    if (!(tmp = strchr(sens, ':'))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Cannot parse sensitivity level in %s"),
+                       sens);
+        goto cleanup;
+    }
+    *tmp = '\0';
+    cat = tmp + 1;
+    /* Find and blank out the sensitivity upper bound */
+    if ((tmp = strchr(sens, '-')))
+        *tmp = '\0';
+    /* sens now just contains the sensitivity lower bound */
+
+    /* Find & extract category min */
+    tmp = cat;
+    if (tmp[0] != 'c') {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Cannot parse category in %s"),
+                       cat);
+        goto cleanup;
+    }
+    tmp++;
+    if (virStrToLong_i(tmp, &tmp, 10, &catMin) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Cannot parse category in %s"),
+                       cat);
+        goto cleanup;
+    }
+
+    /* We *must* have a pair of categories otherwise
+     * there's no range to allocate VM categories from */
+    if (!tmp[0]) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("No category range available"));
+        goto cleanup;
+    }
+
+    /* Find & extract category max (if any) */
+    if (tmp[0] != '.') {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Cannot parse category in %s"),
+                       cat);
+        goto cleanup;
+    }
+    tmp++;
+    if (tmp[0] != 'c') {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Cannot parse category in %s"),
+                       cat);
+        goto cleanup;
+    }
+    tmp++;
+    if (virStrToLong_i(tmp, &tmp, 10, &catMax) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Cannot parse category in %s"),
+                       cat);
+        goto cleanup;
+    }
+
+    /* +1 since virRandomInt range is exclusive of the upper bound */
+    catRange = (catMax - catMin) + 1;
+
+    if (catRange < 8) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Category range c%d-c%d too small"),
+                       catMin, catMax);
+        goto cleanup;
+    }
+
+    VIR_DEBUG("Using sensitivity level '%s' cat min %d max %d range %d",
+              sens, catMin, catMax, catRange);
 
     for (;;) {
-        c1 = virRandomBits(10);
-        c2 = virRandomBits(10);
+        c1 = virRandomInt(catRange);
+        c2 = virRandomInt(catRange);
+        VIR_DEBUG("Try cat %s:c%d,c%d", sens, c1+catMin, c2+catMin);
 
         if (c1 == c2) {
-            if (virAsprintf(&mcs, "s0:c%d", c1) < 0) {
+            if (virAsprintf(&mcs, "%s:c%d", sens, catMin + c1) < 0) {
                 virReportOOMError();
                 return NULL;
             }
@@ -122,7 +217,7 @@ virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr)
                 c1 = c2;
                 c2 = t;
             }
-            if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) {
+            if (virAsprintf(&mcs, "%s:c%d,c%d", sens, catMin + c1, catMin + c2) < 0) {
                 virReportOOMError();
                 return NULL;
             }
@@ -136,6 +231,9 @@ virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr)
 
 cleanup:
     VIR_DEBUG("Found context '%s'", NULLSTR(mcs));
+    VIR_FREE(sens);
+    freecon(ourSecContext);
+    context_free(ourContext);
     return mcs;
 }
 
-- 
1.7.11.2




More information about the libvir-list mailing list