Normally the dynamic labelling mode will always use a base label of 'svirt_t' for VMs. Introduce a <baselabel> field in the <seclabel> XML to allow this base label to be changed eg <seclabel type='dynamic' model='selinux'> <baselabel>system_u:object_r:virt_t:s0</baselabel> </seclabel> * docs/schemas/domain.rng: Add <baselabel> * src/conf/domain_conf.c, src/conf/domain_conf.h: Parsing of base label * src/qemu/qemu_process.c: Don't reset 'model' attribute if a base label is specified * src/security/security_apparmor.c: Refuse to support base label * src/security/security_selinux.c: Use 'baselabel' when generating label, if available --- docs/schemas/domain.rng | 3 ++ src/conf/domain_conf.c | 56 ++++++++++++++++++++++++++----------- src/conf/domain_conf.h | 1 + src/qemu/qemu_process.c | 3 +- src/security/security_apparmor.c | 6 ++++ src/security/security_selinux.c | 29 ++++++++++++++++--- 6 files changed, 75 insertions(+), 23 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 891662d..ab5a56b 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -67,6 +67,9 @@ <element name="imagelabel"> <text/> </element> + <element name="baselabel"> + <text/> + </element> </element> </define> <define name="hvs"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3d290fb..cc318da 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -966,6 +966,7 @@ void virSecurityLabelDefFree(virDomainDefPtr def) VIR_FREE(def->seclabel.model); VIR_FREE(def->seclabel.label); VIR_FREE(def->seclabel.imagelabel); + VIR_FREE(def->seclabel.baselabel); } static void @@ -5072,20 +5073,11 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, goto error; } - /* Only parse details, if using static labels, or + /* Only parse label, if using static labels, or * if the 'live' VM XML is requested */ if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC || !(flags & VIR_DOMAIN_XML_INACTIVE)) { - p = virXPathStringLimit("string(./seclabel/@model)", - VIR_SECURITY_MODEL_BUFLEN-1, ctxt); - if (p == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, - "%s", _("missing security model")); - goto error; - } - def->seclabel.model = p; - p = virXPathStringLimit("string(./seclabel/label[1])", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) { @@ -5110,6 +5102,30 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, def->seclabel.imagelabel = p; } + /* Only parse baselabel, for dynamic label */ + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { + p = virXPathStringLimit("string(./seclabel/baselabel[1])", + VIR_SECURITY_LABEL_BUFLEN-1, ctxt); + if (p != NULL) + def->seclabel.baselabel = p; + } + + /* Only parse model, if static labelling, or a base + * label is set, or doing active XML + */ + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC || + def->seclabel.baselabel || + !(flags & VIR_DOMAIN_XML_INACTIVE)) { + p = virXPathStringLimit("string(./seclabel/@model)", + VIR_SECURITY_MODEL_BUFLEN-1, ctxt); + if (p == NULL) { + virDomainReportError(VIR_ERR_XML_ERROR, + "%s", _("missing security model")); + goto error; + } + def->seclabel.model = p; + } + return 0; error: @@ -9844,20 +9860,26 @@ char *virDomainDefFormat(virDomainDefPtr def, const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type); if (!sectype) goto cleanup; - if (!def->seclabel.label || - (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && - (flags & VIR_DOMAIN_XML_INACTIVE))) { + + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && + !def->seclabel.baselabel && + (flags & VIR_DOMAIN_XML_INACTIVE)) { virBufferAsprintf(&buf, " <seclabel type='%s' model='%s'/>\n", sectype, def->seclabel.model); } else { virBufferAsprintf(&buf, " <seclabel type='%s' model='%s'>\n", - sectype, def->seclabel.model); - virBufferEscapeString(&buf, " <label>%s</label>\n", - def->seclabel.label); + sectype, def->seclabel.model); + if (def->seclabel.label) + virBufferEscapeString(&buf, " <label>%s</label>\n", + def->seclabel.label); if (def->seclabel.imagelabel && - def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) + (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)) virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n", def->seclabel.imagelabel); + if (def->seclabel.baselabel && + (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)) + virBufferEscapeString(&buf, " <baselabel>%s</baselabel>\n", + def->seclabel.baselabel); virBufferAddLit(&buf, " </seclabel>\n"); } } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index aa25e36..17c2584 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -958,6 +958,7 @@ struct _virSecurityLabelDef { char *model; /* name of security model */ char *label; /* security label string */ char *imagelabel; /* security image label string */ + char *baselabel; /* base name of label string */ int type; }; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index bb83be0..1a404ff 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2908,7 +2908,8 @@ void qemuProcessStop(struct qemud_driver *driver, /* Clear out dynamically assigned labels */ if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { - VIR_FREE(vm->def->seclabel.model); + if (!vm->def->seclabel.baselabel) + VIR_FREE(vm->def->seclabel.model); VIR_FREE(vm->def->seclabel.label); VIR_FREE(vm->def->seclabel.imagelabel); } diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index aebf44e..b6ce5b7 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -398,6 +398,12 @@ AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) return 0; + if (vm->def->seclabel.baselabel) { + virSecurityReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("Cannot set a base label with AppArmour")); + return rc; + } + if ((vm->def->seclabel.label) || (vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 0ce999f..736cd7f 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -173,14 +173,29 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) return 0; + if ((vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) && + !vm->def->seclabel.baselabel && + vm->def->seclabel.model) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("security model already defined for VM")); + return rc; + } + if (vm->def->seclabel.label || - vm->def->seclabel.model || vm->def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); return rc; } + if (vm->def->seclabel.model && + STRNEQ(vm->def->seclabel.model, SECURITY_SELINUX_NAME)) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + _("security label model %s is not supported with selinux"), + vm->def->seclabel.model); + return rc; + } + do { c1 = virRandom(1024); c2 = virRandom(1024); @@ -195,7 +210,10 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, } } while(mcsAdd(mcs) == -1); - vm->def->seclabel.label = SELinuxGenNewContext(default_domain_context, mcs); + vm->def->seclabel.label = + SELinuxGenNewContext(vm->def->seclabel.baselabel ? + vm->def->seclabel.baselabel : + default_domain_context, mcs); if (! vm->def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); @@ -207,8 +225,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, _("cannot generate selinux context for %s"), mcs); goto err; } - vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME); - if (!vm->def->seclabel.model) { + if (!vm->def->seclabel.model && + !(vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) { virReportOOMError(); goto err; } @@ -219,7 +237,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, err: VIR_FREE(vm->def->seclabel.label); VIR_FREE(vm->def->seclabel.imagelabel); - VIR_FREE(vm->def->seclabel.model); + if (!vm->def->seclabel.baselabel) + VIR_FREE(vm->def->seclabel.model); done: VIR_FREE(scontext); return rc; -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list