From: "Daniel P. Berrange" <berrange(a)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(a)redhat.com>
---
src/security/security_selinux.c | 88 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 84 insertions(+), 4 deletions(-)
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 4963ef5..714ec4d 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -106,13 +106,90 @@ virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr)
int c1 = 0;
int c2 = 0;
char *mcs = NULL;
+ security_context_t curseccontext = NULL;
+ context_t curcontext = NULL;
+ char *sens, *cat, *tmp;
+ int catMin, catMax, catRange;
+
+ if (getcon(&curseccontext) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to get current process SELinux
context"));
+ goto cleanup;
+ }
+ if (!(curcontext = context_new(curseccontext))) {
+ virReportSystemError(errno,
+ _("Unable to parse current SELinux context
'%s'"),
+ curseccontext);
+ goto cleanup;
+ }
+
+ if (!(sens = strdup(context_range_get(curcontext)))) {
+ 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 */
+ 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;
+ }
+ 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;
+ }
+
+ /* max is inclusive, hence the + 1 */
+ catRange = (catMax - catMin) + 1;
+
+ 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 = virRandom(catRange);
+ c2 = virRandom(catRange);
+ VIR_DEBUG("Try cat %s:c%d,c%d", sens, c1, c2);
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 +199,7 @@ virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr)
c2 ^= c1;
c1 ^= c2;
}
- 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 +213,9 @@ virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr)
cleanup:
VIR_DEBUG("Found context '%s'", NULLSTR(mcs));
+ VIR_FREE(sens);
+ freecon(curseccontext);
+ context_free(curcontext);
return mcs;
}
--
1.7.11.2