diff --git a/0001-Make-virSecurityDeviceLabelDefParseXML-into-generic-.patch b/0001-Make-virSecurityDeviceLabelDefParseXML-into-generic-.patch new file mode 100644 index 0000000..a08f6f3 --- /dev/null +++ b/0001-Make-virSecurityDeviceLabelDefParseXML-into-generic-.patch @@ -0,0 +1,138 @@ +From db2aff6adaa405f0bc998c7bd3158fe43805ee60 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 20 Sep 2012 14:58:12 +0100 +Subject: [PATCH 1/2] Make virSecurityDeviceLabelDefParseXML into generic + device parser. + +This is just code motion, allowing us to reuse the same function to +parse the from character devices too. + +However it also fixes a possible segfault in the original code if +VIR_ALLOC_N returns an error and the cleanup code (at the error: +label) tries to iterate over the unallocated array (thanks Michal +Privoznik for spotting this). + +Signed-off-by: Richard W.M. Jones +--- + src/conf/domain_conf.c | 43 +++++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 18 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 947cc7a..26c2042 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -3258,29 +3258,30 @@ error: + return -1; + } + ++/* Parse the from a disk or character device. */ + static int +-virSecurityDeviceLabelDefParseXML(virDomainDiskDefPtr def, ++virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn, ++ size_t *nseclabels_rtn, + virSecurityLabelDefPtr *vmSeclabels, + int nvmSeclabels, xmlXPathContextPtr ctxt) + { ++ virSecurityDeviceLabelDefPtr *seclabels; ++ size_t nseclabels = 0; + int n, i, j; + xmlNodePtr *list = NULL; + virSecurityLabelDefPtr vmDef = NULL; + char *model, *relabel, *label; + +- if (def == NULL) +- return 0; +- + if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) == 0) + return 0; + +- def->nseclabels = n; +- if (VIR_ALLOC_N(def->seclabels, n) < 0) { ++ if (VIR_ALLOC_N(seclabels, n) < 0) { + virReportOOMError(); + goto error; + } ++ nseclabels = n; + for (i = 0; i < n; i++) { +- if (VIR_ALLOC(def->seclabels[i]) < 0) { ++ if (VIR_ALLOC(seclabels[i]) < 0) { + virReportOOMError(); + goto error; + } +@@ -3297,7 +3298,7 @@ virSecurityDeviceLabelDefParseXML(virDomainDiskDefPtr def, + break; + } + } +- def->seclabels[i]->model = model; ++ seclabels[i]->model = model; + } + + /* Can't use overrides if top-level doesn't allow relabeling. */ +@@ -3311,9 +3312,9 @@ virSecurityDeviceLabelDefParseXML(virDomainDiskDefPtr def, + relabel = virXMLPropString(list[i], "relabel"); + if (relabel != NULL) { + if (STREQ(relabel, "yes")) { +- def->seclabels[i]->norelabel = false; ++ seclabels[i]->norelabel = false; + } else if (STREQ(relabel, "no")) { +- def->seclabels[i]->norelabel = true; ++ seclabels[i]->norelabel = true; + } else { + virReportError(VIR_ERR_XML_ERROR, + _("invalid security relabel value %s"), +@@ -3323,30 +3324,34 @@ virSecurityDeviceLabelDefParseXML(virDomainDiskDefPtr def, + } + VIR_FREE(relabel); + } else { +- def->seclabels[i]->norelabel = false; ++ seclabels[i]->norelabel = false; + } + + ctxt->node = list[i]; + label = virXPathStringLimit("string(./label)", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); +- def->seclabels[i]->label = label; ++ seclabels[i]->label = label; + +- if (label && def->seclabels[i]->norelabel) { ++ if (label && seclabels[i]->norelabel) { + virReportError(VIR_ERR_XML_ERROR, + _("Cannot specify a label if relabelling is " + "turned off. model=%s"), +- NULLSTR(def->seclabels[i]->model)); ++ NULLSTR(seclabels[i]->model)); + goto error; + } + } + VIR_FREE(list); ++ ++ *nseclabels_rtn = nseclabels; ++ *seclabels_rtn = seclabels; ++ + return 0; + + error: +- for (i = 0; i < n; i++) { +- virSecurityDeviceLabelDefFree(def->seclabels[i]); ++ for (i = 0; i < nseclabels; i++) { ++ virSecurityDeviceLabelDefFree(seclabels[i]); + } +- VIR_FREE(def->seclabels); ++ VIR_FREE(seclabels); + VIR_FREE(list); + return -1; + } +@@ -3839,7 +3844,9 @@ virDomainDiskDefParseXML(virCapsPtr caps, + if (sourceNode) { + xmlNodePtr saved_node = ctxt->node; + ctxt->node = sourceNode; +- if (virSecurityDeviceLabelDefParseXML(def, vmSeclabels, ++ if (virSecurityDeviceLabelDefParseXML(&def->seclabels, ++ &def->nseclabels, ++ vmSeclabels, + nvmSeclabels, + ctxt) < 0) + goto error; +-- +1.7.11.4 + diff --git a/0002-Add-seclabel-to-character-devices.patch b/0002-Add-seclabel-to-character-devices.patch new file mode 100644 index 0000000..9e2e565 --- /dev/null +++ b/0002-Add-seclabel-to-character-devices.patch @@ -0,0 +1,440 @@ +From f8b08d0e961c7e10d87ee011ec7bf1f8fe7b1fbb Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 20 Sep 2012 14:16:17 +0100 +Subject: [PATCH 2/2] Add to character devices. + +This allows the user to control labelling of each character device +separately (the default is to inherit from the VM). + +Signed-off-by: Richard W.M. Jones +--- + docs/formatdomain.html.in | 8 ++++ + docs/schemas/domaincommon.rng | 3 ++ + src/conf/domain_conf.c | 78 +++++++++++++++++++++++++++++++++-- + src/conf/domain_conf.h | 6 +++ + src/security/security_selinux.c | 90 +++++++++++++++++++++++++++++------------ + 5 files changed, 155 insertions(+), 30 deletions(-) + + +diff -ur libvirt-0.10.1.old/docs/formatdomain.html.in libvirt-0.10.1/docs/formatdomain.html.in +--- libvirt-0.10.1.old/docs/formatdomain.html.in 2012-08-31 11:01:18.000000000 +0100 ++++ libvirt-0.10.1/docs/formatdomain.html.in 2012-09-21 18:46:30.795973766 +0100 +@@ -3369,6 +3369,14 @@ +

+ +

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

++ ++

+ Each character device element has an optional + sub-element <address> which can tie the + device to a +diff -ur libvirt-0.10.1.old/docs/schemas/domaincommon.rng libvirt-0.10.1/docs/schemas/domaincommon.rng +--- libvirt-0.10.1.old/docs/schemas/domaincommon.rng 2012-08-22 10:05:18.000000000 +0100 ++++ libvirt-0.10.1/docs/schemas/domaincommon.rng 2012-09-21 18:46:30.802973900 +0100 +@@ -2344,6 +2344,9 @@ + + + ++ ++ ++ + + + +diff -ur libvirt-0.10.1.old/src/conf/domain_conf.c libvirt-0.10.1/src/conf/domain_conf.c +--- libvirt-0.10.1.old/src/conf/domain_conf.c 2012-09-21 18:46:07.045533923 +0100 ++++ libvirt-0.10.1/src/conf/domain_conf.c 2012-09-21 18:47:34.781159182 +0100 +@@ -1257,6 +1257,8 @@ + + void virDomainChrDefFree(virDomainChrDefPtr def) + { ++ size_t i; ++ + if (!def) + return; + +@@ -1280,6 +1282,12 @@ + virDomainChrSourceDefClear(&def->source); + virDomainDeviceInfoClear(&def->info); + ++ if (def->seclabels) { ++ for (i = 0; i < def->nseclabels; i++) ++ virSecurityDeviceLabelDefFree(def->seclabels[i]); ++ VIR_FREE(def->seclabels); ++ } ++ + VIR_FREE(def); + } + +@@ -5264,7 +5272,11 @@ + * , which is used by but not ). */ + static int + virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, +- xmlNodePtr cur, unsigned int flags) ++ xmlNodePtr cur, unsigned int flags, ++ virDomainChrDefPtr chr_def, ++ xmlXPathContextPtr ctxt, ++ virSecurityLabelDefPtr* vmSeclabels, ++ int nvmSeclabels) + { + char *bindHost = NULL; + char *bindService = NULL; +@@ -5319,6 +5331,21 @@ + if (def->type == VIR_DOMAIN_CHR_TYPE_UDP) + VIR_FREE(mode); + } ++ ++ /* Check for an optional seclabel override in . */ ++ if (chr_def) { ++ xmlNodePtr saved_node = ctxt->node; ++ ctxt->node = cur; ++ if (virSecurityDeviceLabelDefParseXML(&chr_def->seclabels, ++ &chr_def->nseclabels, ++ vmSeclabels, ++ nvmSeclabels, ++ ctxt) < 0) { ++ ctxt->node = saved_node; ++ goto error; ++ } ++ ctxt->node = saved_node; ++ } + } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) { + if (protocol == NULL) + protocol = virXMLPropString(cur, "type"); +@@ -5512,7 +5539,10 @@ + static virDomainChrDefPtr + virDomainChrDefParseXML(virCapsPtr caps, + virDomainDefPtr vmdef, ++ xmlXPathContextPtr ctxt, + xmlNodePtr node, ++ virSecurityLabelDefPtr* vmSeclabels, ++ int nvmSeclabels, + unsigned int flags) + { + xmlNodePtr cur; +@@ -5543,7 +5573,9 @@ + } + + cur = node->children; +- remaining = virDomainChrSourceDefParseXML(&def->source, cur, flags); ++ remaining = virDomainChrSourceDefParseXML(&def->source, cur, flags, ++ def, ctxt, ++ vmSeclabels, nvmSeclabels); + if (remaining < 0) + goto error; + if (remaining) { +@@ -5680,7 +5712,8 @@ + } + + cur = node->children; +- if (virDomainChrSourceDefParseXML(&def->data.passthru, cur, flags) < 0) ++ if (virDomainChrSourceDefParseXML(&def->data.passthru, cur, flags, ++ NULL, NULL, NULL, 0) < 0) + goto error; + + if (def->data.passthru.type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) { +@@ -7161,7 +7194,8 @@ + if (xmlStrEqual(cur->name, BAD_CAST "source")) { + int remaining; + +- remaining = virDomainChrSourceDefParseXML(&def->source.chr, cur, flags); ++ remaining = virDomainChrSourceDefParseXML(&def->source.chr, cur, flags, ++ NULL, NULL, NULL, 0); + if (remaining != 0) + goto error; + } +@@ -8974,7 +9008,10 @@ + for (i = 0 ; i < n ; i++) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(caps, + def, ++ ctxt, + nodes[i], ++ def->seclabels, ++ def->nseclabels, + flags); + if (!chr) + goto error; +@@ -9001,7 +9038,10 @@ + for (i = 0 ; i < n ; i++) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(caps, + def, ++ ctxt, + nodes[i], ++ def->seclabels, ++ def->nseclabels, + flags); + if (!chr) + goto error; +@@ -9031,7 +9071,10 @@ + bool create_stub = true; + virDomainChrDefPtr chr = virDomainChrDefParseXML(caps, + def, ++ ctxt, + nodes[i], ++ def->seclabels, ++ def->nseclabels, + flags); + if (!chr) + goto error; +@@ -9107,7 +9150,10 @@ + for (i = 0 ; i < n ; i++) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(caps, + def, ++ ctxt, + nodes[i], ++ def->seclabels, ++ def->nseclabels, + flags); + if (!chr) + goto error; +@@ -12188,6 +12234,7 @@ + const char *targetType = virDomainChrTargetTypeToString(def->deviceType, + def->targetType); + bool tty_compat; ++ size_t n; + + int ret = 0; + +@@ -12267,6 +12314,14 @@ + return -1; + } + ++ /* Security label overrides, if any. */ ++ if (def->seclabels && def->nseclabels > 0) { ++ virBufferAdjustIndent(buf, 2); ++ for (n = 0; n < def->nseclabels; n++) ++ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]); ++ virBufferAdjustIndent(buf, -2); ++ } ++ + virBufferAsprintf(buf, " \n", elementName); + + return ret; +@@ -15032,6 +15087,21 @@ + { + int i; + ++ if (def == NULL) ++ return NULL; ++ ++ for (i = 0; i < def->nseclabels; i++) { ++ if (STREQ_NULLABLE(def->seclabels[i]->model, model)) ++ return def->seclabels[i]; ++ } ++ return NULL; ++} ++ ++virSecurityDeviceLabelDefPtr ++virDomainChrDefGetSecurityLabelDef(virDomainChrDefPtr def, const char *model) ++{ ++ int i; ++ + if (def == NULL) + return NULL; + +diff -ur libvirt-0.10.1.old/src/conf/domain_conf.h libvirt-0.10.1/src/conf/domain_conf.h +--- libvirt-0.10.1.old/src/conf/domain_conf.h 2012-08-31 13:14:44.000000000 +0100 ++++ libvirt-0.10.1/src/conf/domain_conf.h 2012-09-21 18:46:30.832974475 +0100 +@@ -953,6 +953,9 @@ + virDomainChrSourceDef source; + + virDomainDeviceInfo info; ++ ++ size_t nseclabels; ++ virSecurityDeviceLabelDefPtr *seclabels; + }; + + enum virDomainSmartcardType { +@@ -2074,6 +2077,9 @@ + virSecurityDeviceLabelDefPtr + virDomainDiskDefGetSecurityLabelDef(virDomainDiskDefPtr def, const char *model); + ++virSecurityDeviceLabelDefPtr ++virDomainChrDefGetSecurityLabelDef(virDomainChrDefPtr def, const char *model); ++ + virSecurityLabelDefPtr + virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char *model); + +diff -ur libvirt-0.10.1.old/src/security/security_selinux.c libvirt-0.10.1/src/security/security_selinux.c +--- libvirt-0.10.1.old/src/security/security_selinux.c 2012-08-22 04:19:44.000000000 +0100 ++++ libvirt-0.10.1/src/security/security_selinux.c 2012-09-21 18:46:30.834974513 +0100 +@@ -1213,38 +1213,61 @@ + + static int + virSecuritySELinuxSetSecurityChardevLabel(virDomainDefPtr def, +- virDomainChrSourceDefPtr dev) ++ virDomainChrDefPtr dev, ++ virDomainChrSourceDefPtr dev_source) + + { +- virSecurityLabelDefPtr secdef; ++ virSecurityLabelDefPtr seclabel; ++ virSecurityDeviceLabelDefPtr chr_seclabel = NULL; ++ char *imagelabel = NULL; + char *in = NULL, *out = NULL; + int ret = -1; + +- secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); +- if (secdef == NULL) ++ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); ++ if (seclabel == NULL) + return -1; + +- if (secdef->norelabel) ++ if (dev) ++ chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev, ++ SECURITY_SELINUX_NAME); ++ ++ if (seclabel->norelabel || (chr_seclabel && chr_seclabel->norelabel)) + return 0; + +- switch (dev->type) { ++ if (chr_seclabel) ++ imagelabel = chr_seclabel->label; ++ if (!imagelabel) ++ imagelabel = seclabel->imagelabel; ++ ++ switch (dev_source->type) { + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: +- ret = virSecuritySELinuxSetFilecon(dev->data.file.path, secdef->imagelabel); ++ ret = virSecuritySELinuxSetFilecon(dev_source->data.file.path, ++ imagelabel); ++ break; ++ ++ case VIR_DOMAIN_CHR_TYPE_UNIX: ++ if (!dev_source->data.nix.listen) { ++ if (virSecuritySELinuxSetFilecon(dev_source->data.file.path, ++ imagelabel) < 0) ++ goto done; ++ } ++ ret = 0; + break; + + case VIR_DOMAIN_CHR_TYPE_PIPE: +- if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) || +- (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) { ++ if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) || ++ (virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0)) { + virReportOOMError(); + goto done; + } + if (virFileExists(in) && virFileExists(out)) { +- if ((virSecuritySELinuxSetFilecon(in, secdef->imagelabel) < 0) || +- (virSecuritySELinuxSetFilecon(out, secdef->imagelabel) < 0)) { ++ if ((virSecuritySELinuxSetFilecon(in, imagelabel) < 0) || ++ (virSecuritySELinuxSetFilecon(out, imagelabel) < 0)) { + goto done; + } +- } else if (virSecuritySELinuxSetFilecon(dev->data.file.path, secdef->imagelabel) < 0) { ++ } else if (virSecuritySELinuxSetFilecon(dev_source->data.file.path, ++ imagelabel) < 0) { + goto done; + } + ret = 0; +@@ -1263,30 +1286,44 @@ + + static int + virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def, +- virDomainChrSourceDefPtr dev) ++ virDomainChrDefPtr dev, ++ virDomainChrSourceDefPtr dev_source) + + { +- virSecurityLabelDefPtr secdef; ++ virSecurityLabelDefPtr seclabel; ++ virSecurityDeviceLabelDefPtr chr_seclabel = NULL; + char *in = NULL, *out = NULL; + int ret = -1; + +- secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); +- if (secdef == NULL) ++ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); ++ if (seclabel == NULL) + return -1; + +- if (secdef->norelabel) ++ if (dev) ++ chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev, ++ SECURITY_SELINUX_NAME); ++ if (seclabel->norelabel || (chr_seclabel && chr_seclabel->norelabel)) + return 0; + +- switch (dev->type) { ++ switch (dev_source->type) { + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: +- if (virSecuritySELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0) ++ if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) + goto done; + ret = 0; + break; ++ ++ case VIR_DOMAIN_CHR_TYPE_UNIX: ++ if (!dev_source->data.nix.listen) { ++ if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) ++ goto done; ++ } ++ ret = 0; ++ break; ++ + case VIR_DOMAIN_CHR_TYPE_PIPE: +- if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) || +- (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) { ++ if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) || ++ (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0)) { + virReportOOMError(); + goto done; + } +@@ -1295,7 +1332,7 @@ + (virSecuritySELinuxRestoreSecurityFileLabel(in) < 0)) { + goto done; + } +- } else if (virSecuritySELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0) { ++ } else if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) { + goto done; + } + ret = 0; +@@ -1323,7 +1360,8 @@ + dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) + return 0; + +- return virSecuritySELinuxRestoreSecurityChardevLabel(def, &dev->source); ++ return virSecuritySELinuxRestoreSecurityChardevLabel(def, dev, ++ &dev->source); + } + + +@@ -1345,7 +1383,7 @@ + return virSecuritySELinuxRestoreSecurityFileLabel(database); + + case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: +- return virSecuritySELinuxRestoreSecurityChardevLabel(def, &dev->data.passthru); ++ return virSecuritySELinuxRestoreSecurityChardevLabel(def, NULL, &dev->data.passthru); + + default: + virReportError(VIR_ERR_INTERNAL_ERROR, +@@ -1703,7 +1741,7 @@ + dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) + return 0; + +- return virSecuritySELinuxSetSecurityChardevLabel(def, &dev->source); ++ return virSecuritySELinuxSetSecurityChardevLabel(def, dev, &dev->source); + } + + +@@ -1727,7 +1765,7 @@ + return virSecuritySELinuxSetFilecon(database, data->content_context); + + case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: +- return virSecuritySELinuxSetSecurityChardevLabel(def, &dev->data.passthru); ++ return virSecuritySELinuxSetSecurityChardevLabel(def, NULL, &dev->data.passthru); + + default: + virReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/libvirt.spec b/libvirt.spec index 3930320..74e0940 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -315,7 +315,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 0.10.1 -Release: 4%{?dist}%{?extra_release} +Release: 5%{?dist}%{?extra_release} License: LGPLv2+ Group: Development/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -331,6 +331,9 @@ Patch1: %{name}-dnsmasq-drop-filterwin2k.patch Patch2: %{name}-fix-unwanted-connection-closing.patch # Fix qemu -> qemu-system-i386 (RHBZ#857026). Patch3: 0001-Use-qemu-system-i386-as-binary-instead-of-qemu.patch +# Upstream patches to label sockets for SELinux (RHBZ#853393). +Patch4: 0001-Make-virSecurityDeviceLabelDefParseXML-into-generic-.patch +Patch5: 0002-Add-seclabel-to-character-devices.patch %if %{with_libvirtd} Requires: libvirt-daemon = %{version}-%{release} @@ -1044,6 +1047,8 @@ of recent versions of Linux (and other OSes). %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build %if ! %{with_xen} @@ -1871,6 +1876,9 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd %endif %changelog +* Fri Sep 21 2012 Richard W.M. Jones - 0.10.1-5 +- Add (upstream) patches to label sockets for SELinux (RHBZ#853393). + * Thu Sep 13 2012 Richard W.M. Jones - 0.10.1-4 - Fix for 32 bit qemu renamed to qemu-system-i386 (RHBZ#857026).