render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
b5548f
From f8b08d0e961c7e10d87ee011ec7bf1f8fe7b1fbb Mon Sep 17 00:00:00 2001
b5548f
From: "Richard W.M. Jones" <rjones@redhat.com>
b5548f
Date: Thu, 20 Sep 2012 14:16:17 +0100
b5548f
Subject: [PATCH 2/2] Add <seclabel> to character devices.
b5548f
b5548f
This allows the user to control labelling of each character device
b5548f
separately (the default is to inherit from the VM).
b5548f
b5548f
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
b5548f
---
b5548f
 docs/formatdomain.html.in       |  8 ++++
b5548f
 docs/schemas/domaincommon.rng   |  3 ++
b5548f
 src/conf/domain_conf.c          | 78 +++++++++++++++++++++++++++++++++--
b5548f
 src/conf/domain_conf.h          |  6 +++
b5548f
 src/security/security_selinux.c | 90 +++++++++++++++++++++++++++++------------
b5548f
 5 files changed, 155 insertions(+), 30 deletions(-)
b5548f
b5548f
b5548f
diff -ur libvirt-0.10.1.old/docs/formatdomain.html.in libvirt-0.10.1/docs/formatdomain.html.in
b5548f
--- libvirt-0.10.1.old/docs/formatdomain.html.in	2012-08-31 11:01:18.000000000 +0100
b5548f
+++ libvirt-0.10.1/docs/formatdomain.html.in	2012-09-21 18:46:30.795973766 +0100
b5548f
@@ -3369,6 +3369,14 @@
b5548f
     

b5548f
 
b5548f
     

b5548f
+      The source element may contain an optional
b5548f
+      seclabel to override the way that labelling
b5548f
+      is done on the socket path.  If this element is not present,
b5548f
+      the security label is inherited from
b5548f
+        the per-domain setting.
b5548f
+    

b5548f
+
b5548f
+    

b5548f
       Each character device element has an optional
b5548f
       sub-element <address> which can tie the
b5548f
       device to a
b5548f
diff -ur libvirt-0.10.1.old/docs/schemas/domaincommon.rng libvirt-0.10.1/docs/schemas/domaincommon.rng
b5548f
--- libvirt-0.10.1.old/docs/schemas/domaincommon.rng	2012-08-22 10:05:18.000000000 +0100
b5548f
+++ libvirt-0.10.1/docs/schemas/domaincommon.rng	2012-09-21 18:46:30.802973900 +0100
b5548f
@@ -2344,6 +2344,9 @@
b5548f
         <optional>
b5548f
           <attribute name="wiremode"/>
b5548f
         </optional>
b5548f
+        <optional>
b5548f
+          <ref name='devSeclabel'/>
b5548f
+        </optional>
b5548f
       </element>
b5548f
     </zeroOrMore>
b5548f
     <optional>
b5548f
diff -ur libvirt-0.10.1.old/src/conf/domain_conf.c libvirt-0.10.1/src/conf/domain_conf.c
b5548f
--- libvirt-0.10.1.old/src/conf/domain_conf.c	2012-09-21 18:46:07.045533923 +0100
b5548f
+++ libvirt-0.10.1/src/conf/domain_conf.c	2012-09-21 18:47:34.781159182 +0100
b5548f
@@ -1257,6 +1257,8 @@
b5548f
 
b5548f
 void virDomainChrDefFree(virDomainChrDefPtr def)
b5548f
 {
b5548f
+    size_t i;
b5548f
+
b5548f
     if (!def)
b5548f
         return;
b5548f
 
b5548f
@@ -1280,6 +1282,12 @@
b5548f
     virDomainChrSourceDefClear(&def->source);
b5548f
     virDomainDeviceInfoClear(&def->info);
b5548f
 
b5548f
+    if (def->seclabels) {
b5548f
+        for (i = 0; i < def->nseclabels; i++)
b5548f
+            virSecurityDeviceLabelDefFree(def->seclabels[i]);
b5548f
+        VIR_FREE(def->seclabels);
b5548f
+    }
b5548f
+
b5548f
     VIR_FREE(def);
b5548f
 }
b5548f
 
b5548f
@@ -5264,7 +5272,11 @@
b5548f
  * <target>, which is used by <serial> but not <smartcard>). */
b5548f
 static int
b5548f
 virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
b5548f
-                              xmlNodePtr cur, unsigned int flags)
b5548f
+                              xmlNodePtr cur, unsigned int flags,
b5548f
+                              virDomainChrDefPtr chr_def,
b5548f
+                              xmlXPathContextPtr ctxt,
b5548f
+                              virSecurityLabelDefPtr* vmSeclabels,
b5548f
+                              int nvmSeclabels)
b5548f
 {
b5548f
     char *bindHost = NULL;
b5548f
     char *bindService = NULL;
b5548f
@@ -5319,6 +5331,21 @@
b5548f
                     if (def->type == VIR_DOMAIN_CHR_TYPE_UDP)
b5548f
                         VIR_FREE(mode);
b5548f
                 }
b5548f
+
b5548f
+                /* Check for an optional seclabel override in <source/>. */
b5548f
+                if (chr_def) {
b5548f
+                    xmlNodePtr saved_node = ctxt->node;
b5548f
+                    ctxt->node = cur;
b5548f
+                    if (virSecurityDeviceLabelDefParseXML(&chr_def->seclabels,
b5548f
+                                                          &chr_def->nseclabels,
b5548f
+                                                          vmSeclabels,
b5548f
+                                                          nvmSeclabels,
b5548f
+                                                          ctxt) < 0) {
b5548f
+                        ctxt->node = saved_node;
b5548f
+                        goto error;
b5548f
+                    }
b5548f
+                    ctxt->node = saved_node;
b5548f
+                }
b5548f
             } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
b5548f
                 if (protocol == NULL)
b5548f
                     protocol = virXMLPropString(cur, "type");
b5548f
@@ -5512,7 +5539,10 @@
b5548f
 static virDomainChrDefPtr
b5548f
 virDomainChrDefParseXML(virCapsPtr caps,
b5548f
                         virDomainDefPtr vmdef,
b5548f
+                        xmlXPathContextPtr ctxt,
b5548f
                         xmlNodePtr node,
b5548f
+                        virSecurityLabelDefPtr* vmSeclabels,
b5548f
+                        int nvmSeclabels,
b5548f
                         unsigned int flags)
b5548f
 {
b5548f
     xmlNodePtr cur;
b5548f
@@ -5543,7 +5573,9 @@
b5548f
     }
b5548f
 
b5548f
     cur = node->children;
b5548f
-    remaining = virDomainChrSourceDefParseXML(&def->source, cur, flags);
b5548f
+    remaining = virDomainChrSourceDefParseXML(&def->source, cur, flags,
b5548f
+                                              def, ctxt,
b5548f
+                                              vmSeclabels, nvmSeclabels);
b5548f
     if (remaining < 0)
b5548f
         goto error;
b5548f
     if (remaining) {
b5548f
@@ -5680,7 +5712,8 @@
b5548f
         }
b5548f
 
b5548f
         cur = node->children;
b5548f
-        if (virDomainChrSourceDefParseXML(&def->data.passthru, cur, flags) < 0)
b5548f
+        if (virDomainChrSourceDefParseXML(&def->data.passthru, cur, flags,
b5548f
+                                          NULL, NULL, NULL, 0) < 0)
b5548f
             goto error;
b5548f
 
b5548f
         if (def->data.passthru.type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) {
b5548f
@@ -7161,7 +7194,8 @@
b5548f
             if (xmlStrEqual(cur->name, BAD_CAST "source")) {
b5548f
                 int remaining;
b5548f
 
b5548f
-                remaining = virDomainChrSourceDefParseXML(&def->source.chr, cur, flags);
b5548f
+                remaining = virDomainChrSourceDefParseXML(&def->source.chr, cur, flags,
b5548f
+                                                          NULL, NULL, NULL, 0);
b5548f
                 if (remaining != 0)
b5548f
                     goto error;
b5548f
             }
b5548f
@@ -8974,7 +9008,10 @@
b5548f
     for (i = 0 ; i < n ; i++) {
b5548f
         virDomainChrDefPtr chr = virDomainChrDefParseXML(caps,
b5548f
                                                          def,
b5548f
+                                                         ctxt,
b5548f
                                                          nodes[i],
b5548f
+                                                         def->seclabels,
b5548f
+                                                         def->nseclabels,
b5548f
                                                          flags);
b5548f
         if (!chr)
b5548f
             goto error;
b5548f
@@ -9001,7 +9038,10 @@
b5548f
     for (i = 0 ; i < n ; i++) {
b5548f
         virDomainChrDefPtr chr = virDomainChrDefParseXML(caps,
b5548f
                                                          def,
b5548f
+                                                         ctxt,
b5548f
                                                          nodes[i],
b5548f
+                                                         def->seclabels,
b5548f
+                                                         def->nseclabels,
b5548f
                                                          flags);
b5548f
         if (!chr)
b5548f
             goto error;
b5548f
@@ -9031,7 +9071,10 @@
b5548f
         bool create_stub = true;
b5548f
         virDomainChrDefPtr chr = virDomainChrDefParseXML(caps,
b5548f
                                                          def,
b5548f
+                                                         ctxt,
b5548f
                                                          nodes[i],
b5548f
+                                                         def->seclabels,
b5548f
+                                                         def->nseclabels,
b5548f
                                                          flags);
b5548f
         if (!chr)
b5548f
             goto error;
b5548f
@@ -9107,7 +9150,10 @@
b5548f
     for (i = 0 ; i < n ; i++) {
b5548f
         virDomainChrDefPtr chr = virDomainChrDefParseXML(caps,
b5548f
                                                          def,
b5548f
+                                                         ctxt,
b5548f
                                                          nodes[i],
b5548f
+                                                         def->seclabels,
b5548f
+                                                         def->nseclabels,
b5548f
                                                          flags);
b5548f
         if (!chr)
b5548f
             goto error;
b5548f
@@ -12188,6 +12234,7 @@
b5548f
     const char *targetType = virDomainChrTargetTypeToString(def->deviceType,
b5548f
                                                             def->targetType);
b5548f
     bool tty_compat;
b5548f
+    size_t n;
b5548f
 
b5548f
     int ret = 0;
b5548f
 
b5548f
@@ -12267,6 +12314,14 @@
b5548f
             return -1;
b5548f
     }
b5548f
 
b5548f
+    /* Security label overrides, if any. */
b5548f
+    if (def->seclabels && def->nseclabels > 0) {
b5548f
+        virBufferAdjustIndent(buf, 2);
b5548f
+        for (n = 0; n < def->nseclabels; n++)
b5548f
+            virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
b5548f
+        virBufferAdjustIndent(buf, -2);
b5548f
+    }
b5548f
+
b5548f
     virBufferAsprintf(buf, "    </%s>\n", elementName);
b5548f
 
b5548f
     return ret;
b5548f
@@ -15032,6 +15087,21 @@
b5548f
 {
b5548f
     int i;
b5548f
 
b5548f
+    if (def == NULL)
b5548f
+        return NULL;
b5548f
+
b5548f
+    for (i = 0; i < def->nseclabels; i++) {
b5548f
+        if (STREQ_NULLABLE(def->seclabels[i]->model, model))
b5548f
+            return def->seclabels[i];
b5548f
+    }
b5548f
+    return NULL;
b5548f
+}
b5548f
+
b5548f
+virSecurityDeviceLabelDefPtr
b5548f
+virDomainChrDefGetSecurityLabelDef(virDomainChrDefPtr def, const char *model)
b5548f
+{
b5548f
+    int i;
b5548f
+
b5548f
     if (def == NULL)
b5548f
         return NULL;
b5548f
 
b5548f
diff -ur libvirt-0.10.1.old/src/conf/domain_conf.h libvirt-0.10.1/src/conf/domain_conf.h
b5548f
--- libvirt-0.10.1.old/src/conf/domain_conf.h	2012-08-31 13:14:44.000000000 +0100
b5548f
+++ libvirt-0.10.1/src/conf/domain_conf.h	2012-09-21 18:46:30.832974475 +0100
b5548f
@@ -953,6 +953,9 @@
b5548f
     virDomainChrSourceDef source;
b5548f
 
b5548f
     virDomainDeviceInfo info;
b5548f
+
b5548f
+    size_t nseclabels;
b5548f
+    virSecurityDeviceLabelDefPtr *seclabels;
b5548f
 };
b5548f
 
b5548f
 enum virDomainSmartcardType {
b5548f
@@ -2074,6 +2077,9 @@
b5548f
 virSecurityDeviceLabelDefPtr
b5548f
 virDomainDiskDefGetSecurityLabelDef(virDomainDiskDefPtr def, const char *model);
b5548f
 
b5548f
+virSecurityDeviceLabelDefPtr
b5548f
+virDomainChrDefGetSecurityLabelDef(virDomainChrDefPtr def, const char *model);
b5548f
+
b5548f
 virSecurityLabelDefPtr
b5548f
 virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char *model);
b5548f
 
b5548f
diff -ur libvirt-0.10.1.old/src/security/security_selinux.c libvirt-0.10.1/src/security/security_selinux.c
b5548f
--- libvirt-0.10.1.old/src/security/security_selinux.c	2012-08-22 04:19:44.000000000 +0100
b5548f
+++ libvirt-0.10.1/src/security/security_selinux.c	2012-09-21 18:46:30.834974513 +0100
b5548f
@@ -1213,38 +1213,61 @@
b5548f
 
b5548f
 static int
b5548f
 virSecuritySELinuxSetSecurityChardevLabel(virDomainDefPtr def,
b5548f
-                                          virDomainChrSourceDefPtr dev)
b5548f
+                                          virDomainChrDefPtr dev,
b5548f
+                                          virDomainChrSourceDefPtr dev_source)
b5548f
 
b5548f
 {
b5548f
-    virSecurityLabelDefPtr secdef;
b5548f
+    virSecurityLabelDefPtr seclabel;
b5548f
+    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
b5548f
+    char *imagelabel = NULL;
b5548f
     char *in = NULL, *out = NULL;
b5548f
     int ret = -1;
b5548f
 
b5548f
-    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
b5548f
-    if (secdef == NULL)
b5548f
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
b5548f
+    if (seclabel == NULL)
b5548f
         return -1;
b5548f
 
b5548f
-    if (secdef->norelabel)
b5548f
+    if (dev)
b5548f
+        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
b5548f
+                                                          SECURITY_SELINUX_NAME);
b5548f
+
b5548f
+    if (seclabel->norelabel || (chr_seclabel && chr_seclabel->norelabel))
b5548f
         return 0;
b5548f
 
b5548f
-    switch (dev->type) {
b5548f
+    if (chr_seclabel)
b5548f
+        imagelabel = chr_seclabel->label;
b5548f
+    if (!imagelabel)
b5548f
+        imagelabel = seclabel->imagelabel;
b5548f
+
b5548f
+    switch (dev_source->type) {
b5548f
     case VIR_DOMAIN_CHR_TYPE_DEV:
b5548f
     case VIR_DOMAIN_CHR_TYPE_FILE:
b5548f
-        ret = virSecuritySELinuxSetFilecon(dev->data.file.path, secdef->imagelabel);
b5548f
+        ret = virSecuritySELinuxSetFilecon(dev_source->data.file.path,
b5548f
+                                           imagelabel);
b5548f
+        break;
b5548f
+
b5548f
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
b5548f
+        if (!dev_source->data.nix.listen) {
b5548f
+            if (virSecuritySELinuxSetFilecon(dev_source->data.file.path,
b5548f
+                                             imagelabel) < 0)
b5548f
+                goto done;
b5548f
+        }
b5548f
+        ret = 0;
b5548f
         break;
b5548f
 
b5548f
     case VIR_DOMAIN_CHR_TYPE_PIPE:
b5548f
-        if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
b5548f
-            (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
b5548f
+        if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) ||
b5548f
+            (virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0)) {
b5548f
             virReportOOMError();
b5548f
             goto done;
b5548f
         }
b5548f
         if (virFileExists(in) && virFileExists(out)) {
b5548f
-            if ((virSecuritySELinuxSetFilecon(in, secdef->imagelabel) < 0) ||
b5548f
-                (virSecuritySELinuxSetFilecon(out, secdef->imagelabel) < 0)) {
b5548f
+            if ((virSecuritySELinuxSetFilecon(in, imagelabel) < 0) ||
b5548f
+                (virSecuritySELinuxSetFilecon(out, imagelabel) < 0)) {
b5548f
                 goto done;
b5548f
             }
b5548f
-        } else if (virSecuritySELinuxSetFilecon(dev->data.file.path, secdef->imagelabel) < 0) {
b5548f
+        } else if (virSecuritySELinuxSetFilecon(dev_source->data.file.path,
b5548f
+                                                imagelabel) < 0) {
b5548f
             goto done;
b5548f
         }
b5548f
         ret = 0;
b5548f
@@ -1263,30 +1286,44 @@
b5548f
 
b5548f
 static int
b5548f
 virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def,
b5548f
-                                              virDomainChrSourceDefPtr dev)
b5548f
+                                              virDomainChrDefPtr dev,
b5548f
+                                              virDomainChrSourceDefPtr dev_source)
b5548f
 
b5548f
 {
b5548f
-    virSecurityLabelDefPtr secdef;
b5548f
+    virSecurityLabelDefPtr seclabel;
b5548f
+    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
b5548f
     char *in = NULL, *out = NULL;
b5548f
     int ret = -1;
b5548f
 
b5548f
-    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
b5548f
-    if (secdef == NULL)
b5548f
+    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
b5548f
+    if (seclabel == NULL)
b5548f
         return -1;
b5548f
 
b5548f
-    if (secdef->norelabel)
b5548f
+    if (dev)
b5548f
+        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
b5548f
+                                                          SECURITY_SELINUX_NAME);
b5548f
+    if (seclabel->norelabel || (chr_seclabel && chr_seclabel->norelabel))
b5548f
         return 0;
b5548f
 
b5548f
-    switch (dev->type) {
b5548f
+    switch (dev_source->type) {
b5548f
     case VIR_DOMAIN_CHR_TYPE_DEV:
b5548f
     case VIR_DOMAIN_CHR_TYPE_FILE:
b5548f
-        if (virSecuritySELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0)
b5548f
+        if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0)
b5548f
             goto done;
b5548f
         ret = 0;
b5548f
         break;
b5548f
+
b5548f
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
b5548f
+        if (!dev_source->data.nix.listen) {
b5548f
+            if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0)
b5548f
+                goto done;
b5548f
+        }
b5548f
+        ret = 0;
b5548f
+        break;
b5548f
+
b5548f
     case VIR_DOMAIN_CHR_TYPE_PIPE:
b5548f
-        if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
b5548f
-            (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
b5548f
+        if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) ||
b5548f
+            (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0)) {
b5548f
             virReportOOMError();
b5548f
             goto done;
b5548f
         }
b5548f
@@ -1295,7 +1332,7 @@
b5548f
                 (virSecuritySELinuxRestoreSecurityFileLabel(in) < 0)) {
b5548f
                 goto done;
b5548f
             }
b5548f
-        } else if (virSecuritySELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0) {
b5548f
+        } else if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) {
b5548f
             goto done;
b5548f
         }
b5548f
         ret = 0;
b5548f
@@ -1323,7 +1360,8 @@
b5548f
         dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
b5548f
         return 0;
b5548f
 
b5548f
-    return virSecuritySELinuxRestoreSecurityChardevLabel(def, &dev->source);
b5548f
+    return virSecuritySELinuxRestoreSecurityChardevLabel(def, dev,
b5548f
+                                                         &dev->source);
b5548f
 }
b5548f
 
b5548f
 
b5548f
@@ -1345,7 +1383,7 @@
b5548f
         return virSecuritySELinuxRestoreSecurityFileLabel(database);
b5548f
 
b5548f
     case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
b5548f
-        return virSecuritySELinuxRestoreSecurityChardevLabel(def, &dev->data.passthru);
b5548f
+        return virSecuritySELinuxRestoreSecurityChardevLabel(def, NULL, &dev->data.passthru);
b5548f
 
b5548f
     default:
b5548f
         virReportError(VIR_ERR_INTERNAL_ERROR,
b5548f
@@ -1703,7 +1741,7 @@
b5548f
         dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
b5548f
         return 0;
b5548f
 
b5548f
-    return virSecuritySELinuxSetSecurityChardevLabel(def, &dev->source);
b5548f
+    return virSecuritySELinuxSetSecurityChardevLabel(def, dev, &dev->source);
b5548f
 }
b5548f
 
b5548f
 
b5548f
@@ -1727,7 +1765,7 @@
b5548f
         return virSecuritySELinuxSetFilecon(database, data->content_context);
b5548f
 
b5548f
     case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
b5548f
-        return virSecuritySELinuxSetSecurityChardevLabel(def, &dev->data.passthru);
b5548f
+        return virSecuritySELinuxSetSecurityChardevLabel(def, NULL, &dev->data.passthru);
b5548f
 
b5548f
     default:
b5548f
         virReportError(VIR_ERR_INTERNAL_ERROR,