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