mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Allow a base label to be specified in dynamic labelling mode
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
This commit is contained in:
parent
49826eda7a
commit
4ebfc42716
@ -67,6 +67,9 @@
|
|||||||
<element name="imagelabel">
|
<element name="imagelabel">
|
||||||
<text/>
|
<text/>
|
||||||
</element>
|
</element>
|
||||||
|
<element name="baselabel">
|
||||||
|
<text/>
|
||||||
|
</element>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
<define name="hvs">
|
<define name="hvs">
|
||||||
|
@ -966,6 +966,7 @@ void virSecurityLabelDefFree(virDomainDefPtr def)
|
|||||||
VIR_FREE(def->seclabel.model);
|
VIR_FREE(def->seclabel.model);
|
||||||
VIR_FREE(def->seclabel.label);
|
VIR_FREE(def->seclabel.label);
|
||||||
VIR_FREE(def->seclabel.imagelabel);
|
VIR_FREE(def->seclabel.imagelabel);
|
||||||
|
VIR_FREE(def->seclabel.baselabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -5072,20 +5073,11 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def,
|
|||||||
goto error;
|
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 the 'live' VM XML is requested
|
||||||
*/
|
*/
|
||||||
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
|
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
|
||||||
!(flags & VIR_DOMAIN_XML_INACTIVE)) {
|
!(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])",
|
p = virXPathStringLimit("string(./seclabel/label[1])",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@ -5110,6 +5102,30 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def,
|
|||||||
def->seclabel.imagelabel = p;
|
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;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -9844,20 +9860,26 @@ char *virDomainDefFormat(virDomainDefPtr def,
|
|||||||
const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type);
|
const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type);
|
||||||
if (!sectype)
|
if (!sectype)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (!def->seclabel.label ||
|
|
||||||
(def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
|
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
|
||||||
(flags & VIR_DOMAIN_XML_INACTIVE))) {
|
!def->seclabel.baselabel &&
|
||||||
|
(flags & VIR_DOMAIN_XML_INACTIVE)) {
|
||||||
virBufferAsprintf(&buf, " <seclabel type='%s' model='%s'/>\n",
|
virBufferAsprintf(&buf, " <seclabel type='%s' model='%s'/>\n",
|
||||||
sectype, def->seclabel.model);
|
sectype, def->seclabel.model);
|
||||||
} else {
|
} else {
|
||||||
virBufferAsprintf(&buf, " <seclabel type='%s' model='%s'>\n",
|
virBufferAsprintf(&buf, " <seclabel type='%s' model='%s'>\n",
|
||||||
sectype, def->seclabel.model);
|
sectype, def->seclabel.model);
|
||||||
virBufferEscapeString(&buf, " <label>%s</label>\n",
|
if (def->seclabel.label)
|
||||||
def->seclabel.label);
|
virBufferEscapeString(&buf, " <label>%s</label>\n",
|
||||||
|
def->seclabel.label);
|
||||||
if (def->seclabel.imagelabel &&
|
if (def->seclabel.imagelabel &&
|
||||||
def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
|
(def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC))
|
||||||
virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n",
|
virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n",
|
||||||
def->seclabel.imagelabel);
|
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");
|
virBufferAddLit(&buf, " </seclabel>\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -958,6 +958,7 @@ struct _virSecurityLabelDef {
|
|||||||
char *model; /* name of security model */
|
char *model; /* name of security model */
|
||||||
char *label; /* security label string */
|
char *label; /* security label string */
|
||||||
char *imagelabel; /* security image label string */
|
char *imagelabel; /* security image label string */
|
||||||
|
char *baselabel; /* base name of label string */
|
||||||
int type;
|
int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2883,7 +2883,8 @@ void qemuProcessStop(struct qemud_driver *driver,
|
|||||||
|
|
||||||
/* Clear out dynamically assigned labels */
|
/* Clear out dynamically assigned labels */
|
||||||
if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
|
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.label);
|
||||||
VIR_FREE(vm->def->seclabel.imagelabel);
|
VIR_FREE(vm->def->seclabel.imagelabel);
|
||||||
}
|
}
|
||||||
|
@ -398,6 +398,12 @@ AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|||||||
if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
|
if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
|
||||||
return 0;
|
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) ||
|
if ((vm->def->seclabel.label) ||
|
||||||
(vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) {
|
(vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) {
|
||||||
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
@ -173,14 +173,29 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|||||||
if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
|
if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
|
||||||
return 0;
|
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 ||
|
if (vm->def->seclabel.label ||
|
||||||
vm->def->seclabel.model ||
|
|
||||||
vm->def->seclabel.imagelabel) {
|
vm->def->seclabel.imagelabel) {
|
||||||
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("security label already defined for VM"));
|
"%s", _("security label already defined for VM"));
|
||||||
return rc;
|
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 {
|
do {
|
||||||
c1 = virRandom(1024);
|
c1 = virRandom(1024);
|
||||||
c2 = virRandom(1024);
|
c2 = virRandom(1024);
|
||||||
@ -195,7 +210,10 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
} while(mcsAdd(mcs) == -1);
|
} 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) {
|
if (! vm->def->seclabel.label) {
|
||||||
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot generate selinux context for %s"), mcs);
|
_("cannot generate selinux context for %s"), mcs);
|
||||||
@ -207,8 +225,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|||||||
_("cannot generate selinux context for %s"), mcs);
|
_("cannot generate selinux context for %s"), mcs);
|
||||||
goto err;
|
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();
|
virReportOOMError();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -219,7 +237,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|||||||
err:
|
err:
|
||||||
VIR_FREE(vm->def->seclabel.label);
|
VIR_FREE(vm->def->seclabel.label);
|
||||||
VIR_FREE(vm->def->seclabel.imagelabel);
|
VIR_FREE(vm->def->seclabel.imagelabel);
|
||||||
VIR_FREE(vm->def->seclabel.model);
|
if (!vm->def->seclabel.baselabel)
|
||||||
|
VIR_FREE(vm->def->seclabel.model);
|
||||||
done:
|
done:
|
||||||
VIR_FREE(scontext);
|
VIR_FREE(scontext);
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user