diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 65c7c72edd87731d6324c310b0e37039eb9f3bf5..aee03d7fcd5870d24fcfdbfb0a7d0bcdbcc24ca9 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -60,6 +60,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 1acc9366f7b604f84e4caacc5144842e04956129..1eb5e3aa0b8b16a38c94b029b108eda82fb0d607 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -183,6 +183,20 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
caps->host.nnumaCell = 0;
}
+static void
+virCapabilitiesClearSecModel(virCapsHostSecModelPtr secmodel)
+{
+ size_t i;
+ for (i = 0; i < secmodel->nlabels; i++) {
+ VIR_FREE(secmodel->labels[i].type);
+ VIR_FREE(secmodel->labels[i].label);
+ }
+
+ VIR_FREE(secmodel->labels);
+ VIR_FREE(secmodel->model);
+ VIR_FREE(secmodel->doi);
+}
+
static void
virCapabilitiesDispose(void *object)
{
@@ -204,8 +218,7 @@ virCapabilitiesDispose(void *object)
VIR_FREE(caps->host.migrateTrans);
for (i = 0; i < caps->host.nsecModels; i++) {
- VIR_FREE(caps->host.secModels[i].model);
- VIR_FREE(caps->host.secModels[i].doi);
+ virCapabilitiesClearSecModel(&caps->host.secModels[i]);
}
VIR_FREE(caps->host.secModels);
@@ -506,6 +519,44 @@ virCapabilitiesAddGuestFeature(virCapsGuestPtr guest,
return NULL;
}
+/**
+ * virCapabilitiesHostSecModelAddBaseLabel
+ * @secmodel: Security model to add a base label for
+ * @type: virtualization type
+ * @label: base label
+ *
+ * Returns non-zero on error.
+ */
+extern int
+virCapabilitiesHostSecModelAddBaseLabel(virCapsHostSecModelPtr secmodel,
+ const char *type,
+ const char *label)
+{
+ char *t = NULL, *l = NULL;
+
+ if (type == NULL || label == NULL)
+ return -1;
+
+ if (VIR_STRDUP(t, type) < 0)
+ goto no_memory;
+
+ if (VIR_STRDUP(l, label) < 0)
+ goto no_memory;
+
+ if (VIR_EXPAND_N(secmodel->labels, secmodel->nlabels, 1) < 0)
+ goto no_memory;
+
+ secmodel->labels[secmodel->nlabels - 1].type = t;
+ secmodel->labels[secmodel->nlabels - 1].label = l;
+
+ return 0;
+
+no_memory:
+ VIR_FREE(l);
+ VIR_FREE(t);
+ return -1;
+}
+
/**
* virCapabilitiesSupportsGuestArch:
* @caps: capabilities to query
@@ -826,6 +877,11 @@ virCapabilitiesFormatXML(virCapsPtr caps)
caps->host.secModels[i].model);
virBufferAsprintf(&xml, " %s\n",
caps->host.secModels[i].doi);
+ for (j = 0; j < caps->host.secModels[i].nlabels; j++) {
+ virBufferAsprintf(&xml, " %s\n",
+ caps->host.secModels[i].labels[j].type,
+ caps->host.secModels[i].labels[j].label);
+ }
virBufferAddLit(&xml, " \n");
}
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index 88ec4547f7ff9ebbf2c369cd49d3c79f47ef6e11..5bc7bb502343a973eb2fe42a4a4edfa600059973 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -104,11 +104,20 @@ struct _virCapsHostNUMACell {
virCapsHostNUMACellCPUPtr cpus;
};
+typedef struct _virCapsHostSecModelLabel virCapsHostSecModelLabel;
+typedef virCapsHostSecModelLabel *virCapsHostSecModelLabelPtr;
+struct _virCapsHostSecModelLabel {
+ char *type;
+ char *label;
+};
+
typedef struct _virCapsHostSecModel virCapsHostSecModel;
typedef virCapsHostSecModel *virCapsHostSecModelPtr;
struct _virCapsHostSecModel {
char *model;
char *doi;
+ size_t nlabels;
+ virCapsHostSecModelLabelPtr labels;
};
typedef struct _virCapsHost virCapsHost;
@@ -224,6 +233,11 @@ virCapabilitiesAddGuestFeature(virCapsGuestPtr guest,
int defaultOn,
int toggle);
+extern int
+virCapabilitiesHostSecModelAddBaseLabel(virCapsHostSecModelPtr secmodel,
+ const char *type,
+ const char *label);
+
extern int
virCapabilitiesSupportsGuestArch(virCapsPtr caps,
virArch arch);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 092f79749c468028a39a0e1c5437ad834c5298df..675835f040a5ac72b100e4f52cb3148d236680fb 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -58,6 +58,7 @@ virCapabilitiesFormatXML;
virCapabilitiesFreeMachines;
virCapabilitiesFreeNUMAInfo;
virCapabilitiesGetCpusForNodemask;
+virCapabilitiesHostSecModelAddBaseLabel;
virCapabilitiesNew;
virCapabilitiesSetHostCPU;
diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c
index c1cee3f841810e245515635933290cddcdbea651..557191aec0cbe4f0cd438176d44207d1c36ec858 100644
--- a/src/lxc/lxc_conf.c
+++ b/src/lxc/lxc_conf.c
@@ -126,10 +126,13 @@ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver)
if (driver) {
/* Security driver data */
- const char *doi, *model;
+ const char *doi, *model, *label, *type;
doi = virSecurityManagerGetDOI(driver->securityManager);
model = virSecurityManagerGetModel(driver->securityManager);
+ label = virSecurityManagerGetBaseLabel(driver->securityManager,
+ VIR_DOMAIN_VIRT_LXC);
+ type = virDomainVirtTypeToString(VIR_DOMAIN_VIRT_LXC);
/* Allocate the primary security driver for LXC. */
if (VIR_ALLOC(caps->host.secModels) < 0)
goto error;
@@ -138,6 +141,11 @@ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver)
goto error;
if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0)
goto error;
+ if (label &&
+ virCapabilitiesHostSecModelAddBaseLabel(&caps->host.secModels[0],
+ type,
+ label) < 0)
+ goto error;
VIR_DEBUG("Initialized caps for security driver \"%s\" with "
"DOI \"%s\"", model, doi);
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 4ef9c758884519a5cc7ea16dcf8809a5015f4f47..03c9c7d486d27c0ad0614d683b67ad66a468d2d0 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -605,12 +605,14 @@ virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver)
virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver)
{
- size_t i;
+ size_t i, j;
virCapsPtr caps;
virSecurityManagerPtr *sec_managers = NULL;
/* Security driver data */
- const char *doi, *model;
+ const char *doi, *model, *lbl, *type;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ const int virtTypes[] = {VIR_DOMAIN_VIRT_KVM,
+ VIR_DOMAIN_VIRT_QEMU,};
/* Basic host arch / guest machine capabilities */
if (!(caps = virQEMUCapsInit(driver->qemuCapsCache)))
@@ -635,11 +637,21 @@ virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver)
goto error;
for (i = 0; sec_managers[i]; i++) {
+ virCapsHostSecModelPtr sm = &caps->host.secModels[i];
doi = virSecurityManagerGetDOI(sec_managers[i]);
model = virSecurityManagerGetModel(sec_managers[i]);
- if (VIR_STRDUP(caps->host.secModels[i].model, model) < 0 ||
- VIR_STRDUP(caps->host.secModels[i].doi, doi) < 0)
+ if (VIR_STRDUP(sm->model, model) < 0 ||
+ VIR_STRDUP(sm->doi, doi) < 0)
goto error;
+
+ for (j = 0; j < ARRAY_CARDINALITY(virtTypes); j++) {
+ lbl = virSecurityManagerGetBaseLabel(sec_managers[i], virtTypes[j]);
+ type = virDomainVirtTypeToString(virtTypes[j]);
+ if (lbl &&
+ virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0)
+ goto error;
+ }
+
VIR_DEBUG("Initialized caps for security driver \"%s\" with "
"DOI \"%s\"", model, doi);
}
diff --git a/tests/capabilityschemadata/caps-qemu-kvm.xml b/tests/capabilityschemadata/caps-qemu-kvm.xml
index de0c57feb408c7d6b2eb9f922d6b549fcf212647..55faa16b2d3a1efdc5ce8e9ef12c062e921501c2 100644
--- a/tests/capabilityschemadata/caps-qemu-kvm.xml
+++ b/tests/capabilityschemadata/caps-qemu-kvm.xml
@@ -25,6 +25,8 @@
selinux
0
+ system_u:system_r:svirt_t:s0
+ system_u:system_r:svirt_tcg_t:s0
diff --git a/tests/capabilityschemadata/caps-test3.xml b/tests/capabilityschemadata/caps-test3.xml
index e6c56c55f98f3364e036f705a2ce9930d6347ade..7e21f850488a531a2e385a12f7532db04868cf2a 100644
--- a/tests/capabilityschemadata/caps-test3.xml
+++ b/tests/capabilityschemadata/caps-test3.xml
@@ -82,6 +82,8 @@
dac
0
+ 107:107
+ 107:107