1
0
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:
Daniel P. Berrange 2011-06-23 15:48:48 +01:00
parent 49826eda7a
commit 4ebfc42716
6 changed files with 75 additions and 23 deletions

View File

@ -67,6 +67,9 @@
<element name="imagelabel">
<text/>
</element>
<element name="baselabel">
<text/>
</element>
</element>
</define>
<define name="hvs">

View File

@ -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");
}
}

View File

@ -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;
};

View File

@ -2883,7 +2883,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);
}

View File

@ -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,

View File

@ -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;