[libvirt] [PATCH v3 2/5] Multiple security drivers in XML data

Michal Privoznik mprivozn at redhat.com
Mon Aug 6 13:30:03 UTC 2012


On 03.08.2012 16:18, Marcelo Cerri wrote:
> This patch updates the domain and capability XML parser and formatter to
> support morethan one "seclabel" element for each domain and device. The
> RNG schema and the tests related to this are also updated by this patch.
> 
> Signed-off-by: Marcelo Cerri <mhcerri at linux.vnet.ibm.com>
> ---
>  docs/formatdomain.html.in                          |   11 +-
>  docs/schemas/capability.rng                        |   18 +-
>  docs/schemas/domaincommon.rng                      |   30 ++-
>  src/conf/capabilities.c                            |    6 +-
>  src/conf/domain_conf.c                             |  353 ++++++++++++++------
>  src/conf/domain_conf.h                             |    9 +
>  src/libvirt_private.syms                           |    3 +
>  .../qemuxml2argv-seclabel-dynamic-override.xml     |    4 +-
>  .../qemuxml2argv-seclabel-dynamic.xml              |    2 +-
>  9 files changed, 305 insertions(+), 131 deletions(-)
> 
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index f97c630..88e0418 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -1273,8 +1273,8 @@
>          path to the file holding the disk. If the disk
>          <code>type</code> is "block", then the <code>dev</code>
>          attribute specifies the path to the host device to serve as
> -        the disk. With both "file" and "block", an optional
> -        sub-element <code>seclabel</code>, <a href="#seclabel">described
> +        the disk. With both "file" and "block", one or more optional
> +        sub-elements <code>seclabel</code>, <a href="#seclabel">described
>          below</a> (and <span class="since">since 0.9.9</span>), can be
>          used to override the domain security labeling policy for just
>          that source file.  If the disk <code>type</code> is "dir", then the
> @@ -3828,6 +3828,13 @@ qemu-kvm -net nic,model=? /dev/null
>      </p>
>  
>      <p>
> +      If more than one security driver is used by libvirt, multiple
> +      <code>seclabel</code> tags can be used, one for each driver and
> +      the security driver referenced by each tag can be defined using
> +      the attribute <code>model</code>
> +    </p>
> +
> +    <p>
>        Valid input XML configurations for the top-level security label
>        are:
>      </p>
> diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
> index c392e44..8c928bc 100644
> --- a/docs/schemas/capability.rng
> +++ b/docs/schemas/capability.rng
> @@ -44,20 +44,22 @@
>        <optional>
>          <ref name='topology'/>
>        </optional>
> -      <optional>
> +      <zeroOrMore>
>          <ref name='secmodel'/>
> -      </optional>
> +      </zeroOrMore>
>      </element>
>    </define>
>  
>    <define name='secmodel'>
>      <element name='secmodel'>
> -      <element name='model'>
> -        <text/>
> -      </element>
> -      <element name='doi'>
> -        <text/>
> -      </element>
> +      <interleave>
> +          <element name='model'>
> +            <text/>
> +          </element>
> +          <element name='doi'>
> +            <text/>
> +          </element>
> +       </interleave>
>      </element>
>    </define>
>  
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index c85d763..d1c1683 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -55,9 +55,9 @@
>          <optional>
>            <ref name="devices"/>
>          </optional>
> -        <optional>
> +        <zeroOrMore>
>            <ref name="seclabel"/>
> -        </optional>
> +        </zeroOrMore>
>          <optional>
>            <ref name='qemucmdline'/>
>          </optional>
> @@ -148,18 +148,32 @@
>        <!-- A per-device seclabel override is more limited, either
>             relabel=no or a <label> must be present.  -->
>        <choice>
> -        <attribute name='relabel'>
> -          <value>no</value>
> -        </attribute>
>          <group>
>            <optional>
> +            <attribute name='model'>
> +              <text/>
> +            </attribute>
> +          </optional>
> +          <attribute name='relabel'>
> +            <value>no</value>
> +          </attribute>
> +        </group>
> +        <group>
> +          <optional>
> +            <attribute name='model'>
> +              <text/>
> +            </attribute>
> +          </optional>
> +          <optional>

IIUC, both 'model' and 'relabel' are purely optional. If that is the
case, the first <group> can be left out.

>              <attribute name='relabel'>
>                <value>yes</value>
>              </attribute>
>            </optional>
> -          <element name='label'>
> -            <text/>
> -          </element>
> +          <zeroOrMore>
> +            <element name='label'>
> +              <text/>
> +            </element>
> +          </zeroOrMore>
>          </group>
>        </choice>
>      </element>
> diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
> index 9a0bc3d..bc6266e 100644
> --- a/src/conf/capabilities.c
> +++ b/src/conf/capabilities.c
> @@ -772,12 +772,12 @@ virCapabilitiesFormatXML(virCapsPtr caps)
>          virBufferAddLit(&xml, "    </topology>\n");
>      }
>  
> -    if (caps->host.nsecModels) {
> +    for (i = 0; i < caps->host.nsecModels; i++) {
>          virBufferAddLit(&xml, "    <secmodel>\n");
>          virBufferAsprintf(&xml, "      <model>%s</model>\n",
> -                          caps->host.secModels[0].model);
> +                          caps->host.secModels[i].model);
>          virBufferAsprintf(&xml, "      <doi>%s</doi>\n",
> -                          caps->host.secModels[0].doi);
> +                          caps->host.secModels[i].doi);
>          virBufferAddLit(&xml, "    </secmodel>\n");
>      }
>  
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 1c318a0..866df12 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -3078,17 +3078,19 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
>      return 0;
>  }
>  
> -static int
> -virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
> -                            xmlXPathContextPtr ctxt,
> +static virSecurityLabelDefPtr
> +virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,
>                              unsigned int flags)
>  {
>      char *p;
> +    virSecurityLabelDefPtr def = NULL;
>  
> -    if (virXPathNode("./seclabel[1]", ctxt) == NULL)
> -        return 0;
> +    if (VIR_ALLOC(def) < 0) {
> +        virReportOOMError();
> +        goto error;
> +    }
>  
> -    p = virXPathStringLimit("string(./seclabel[1]/@type)",
> +    p = virXPathStringLimit("string(./@type)",
>                              VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
>      if (p == NULL) {
>          def->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
> @@ -3102,7 +3104,7 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
>          }
>      }
>  
> -    p = virXPathStringLimit("string(./seclabel[1]/@relabel)",
> +    p = virXPathStringLimit("string(./@relabel)",
>                              VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
>      if (p != NULL) {
>          if (STREQ(p, "yes")) {
> @@ -3142,7 +3144,7 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
>      if (def->type == VIR_DOMAIN_SECLABEL_STATIC ||
>          (!(flags & VIR_DOMAIN_XML_INACTIVE) &&
>           def->type != VIR_DOMAIN_SECLABEL_NONE)) {
> -        p = virXPathStringLimit("string(./seclabel[1]/label[1])",
> +        p = virXPathStringLimit("string(./label[1])",
>                                  VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
>          if (p == NULL) {
>              virReportError(VIR_ERR_XML_ERROR,
> @@ -3157,7 +3159,7 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
>      if (!def->norelabel &&
>          (!(flags & VIR_DOMAIN_XML_INACTIVE) &&
>           def->type != VIR_DOMAIN_SECLABEL_NONE)) {
> -        p = virXPathStringLimit("string(./seclabel[1]/imagelabel[1])",
> +        p = virXPathStringLimit("string(./imagelabel[1])",
>                                  VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
>          if (p == NULL) {
>              virReportError(VIR_ERR_XML_ERROR,
> @@ -3169,93 +3171,179 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
>  
>      /* Only parse baselabel for dynamic label type */
>      if (def->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
> -        p = virXPathStringLimit("string(./seclabel[1]/baselabel[1])",
> +        p = virXPathStringLimit("string(./baselabel[1])",
>                                  VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
>          def->baselabel = p;
>      }
>  
> -    /* Only parse model, if static labelling, or a base
> -     * label is set, or doing active XML
> -     */
> -    if (def->type == VIR_DOMAIN_SECLABEL_STATIC ||
> -        def->baselabel ||
> -        (!(flags & VIR_DOMAIN_XML_INACTIVE) &&
> -         def->type != VIR_DOMAIN_SECLABEL_NONE)) {
> -        p = virXPathStringLimit("string(./seclabel[1]/@model)",
> -                                VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
> -        if (p == NULL) {
> -            virReportError(VIR_ERR_XML_ERROR,
> -                           "%s", _("missing security model"));
> -            goto error;
> -        }
> -        def->model = p;
> +    /* Always parse model */
> +    p = virXPathStringLimit("string(./@model)",
> +                            VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
> +    if (p == NULL && def->type != VIR_DOMAIN_SECLABEL_NONE) {
> +        virReportError(VIR_ERR_XML_ERROR,
> +                       "%s", _("missing security model"));
>      }
> +    def->model = p;
>  
> -    return 0;
> +    return def;
>  
>  error:
>      virSecurityLabelDefFree(def);
> +    return NULL;
> +}
> +
> +static int
> +virSecurityLabelDefsParseXML(virDomainDefPtr def,
> +                            xmlXPathContextPtr ctxt,
> +                            unsigned int flags)
> +{
> +    int i, n;
> +    xmlNodePtr *list = NULL, saved_node;
> +
> +    /* Check args and save context */
> +    if (def == NULL || ctxt == NULL)
> +        return 0;
> +    saved_node = ctxt->node;
> +
> +    /* Allocate a security labels based on XML */
> +    if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) == 0)
> +        return 0;
> +
> +    if (VIR_ALLOC_N(def->seclabels, n) < 0) {
> +        virReportOOMError();
> +        goto error;
> +    }
> +
> +    /* Parse each "seclabel" tag */
> +    for (i = 0; i < n; i++) {
> +        ctxt->node = list[i];
> +        def->seclabels[i] = virSecurityLabelDefParseXML(ctxt, flags);
> +        if (def->seclabels[i] == NULL)
> +            goto error;
> +    }
> +    def->nseclabels = n;
> +    ctxt->node = saved_node;
> +    VIR_FREE(list);
> +
> +    /* Checking missing model information
> +     * when there is more than one seclabel */
> +    if (n > 1) {
> +        for(; n; n--) {
> +            if (def->seclabels[n - 1]->model == NULL) {
> +                virReportError(VIR_ERR_XML_ERROR, "%s",
> +                                     _("missing security model "
> +                                       "when using multiple labels"));
> +                goto error;
> +            }
> +        }
> +    }
> +    return 0;
> +
> +error:
> +    ctxt->node = saved_node;
> +    for (; i > 0; i--) {
> +        virSecurityLabelDefFree(def->seclabels[i - 1]);
> +    }
> +    VIR_FREE(def->seclabels);
> +    VIR_FREE(list);
>      return -1;
>  }
>  
> -
>  static int
> -virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr *def,
> -                                  virSecurityLabelDefPtr vmDef,
> -                                  xmlXPathContextPtr ctxt)
> +virSecurityDeviceLabelDefParseXML(virDomainDiskDefPtr def,
> +                                  virSecurityLabelDefPtr *vmSeclabels,
> +                                  int nvmSeclabels, xmlXPathContextPtr ctxt)
>  {
> -    char *p;
> +    int n, i, j;
> +    xmlNodePtr *list = NULL;
> +    virSecurityLabelDefPtr vmDef = NULL;
> +    char *model, *relabel, *label;
>  
> -    *def = NULL;
> -
> -    if (virXPathNode("./seclabel[1]", ctxt) == NULL)
> +    if (def == NULL)
>          return 0;
>  
> -    /* Can't use overrides if top-level doesn't allow relabeling.  */
> -    if (vmDef && vmDef->norelabel) {
> -        virReportError(VIR_ERR_XML_ERROR, "%s",
> -                       _("label overrides require relabeling to be "
> -                         "enabled at the domain level"));
> -        return -1;
> -    }
> +    if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) == 0)
> +        return 0;
>  
> -    if (VIR_ALLOC(*def) < 0) {
> +    def->nseclabels = n;
> +    if (VIR_ALLOC_N(def->seclabels, n) < 0) {
>          virReportOOMError();
> -        return -1;
> +        goto error;
>      }
> +    for (i = 0; i < n; i++) {
> +        if (VIR_ALLOC(def->seclabels[i]) < 0) {
> +            virReportOOMError();
> +            goto error;
> +        }
> +    }
> +
> +    for (i = 0; i < n; i++) {
> +        /* get model associated to this override */
> +        model = virXMLPropString(list[i], "model");
> +        if (model == NULL) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                           _("invalid security model"));
> +            goto error;
> +        } else {
> +            /* find the security label that it's being overriden */
> +            for (j = 0; j < nvmSeclabels; j++) {
> +                if (STREQ(vmSeclabels[j]->model, model)) {
> +                    vmDef = vmSeclabels[j];
> +                    break;
> +                }
> +            }
> +            def->seclabels[i]->model = model;
> +        }
>  
> -    p = virXPathStringLimit("string(./seclabel[1]/@relabel)",
> -                            VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
> -    if (p != NULL) {
> -        if (STREQ(p, "yes")) {
> -            (*def)->norelabel = false;
> -        } else if (STREQ(p, "no")) {
> -            (*def)->norelabel = true;
> +        /* Can't use overrides if top-level doesn't allow relabeling.  */
> +        if (vmDef && vmDef->norelabel) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                           _("label overrides require relabeling to be "
> +                             "enabled at the domain level"));
> +            goto error;
> +        }
> +
> +        relabel = virXMLPropString(list[i], "relabel");
> +        if (relabel != NULL) {
> +            if (STREQ(relabel, "yes")) {
> +                def->seclabels[i]->norelabel = false;
> +            } else if (STREQ(relabel, "no")) {
> +                def->seclabels[i]->norelabel = true;
> +            } else {
> +                virReportError(VIR_ERR_XML_ERROR,
> +                               _("invalid security relabel value %s"),
> +                               relabel);
> +                VIR_FREE(relabel);
> +                goto error;
> +            }
> +            VIR_FREE(relabel);
>          } else {
> +            def->seclabels[i]->norelabel = false;
> +        }
> +
> +        ctxt->node = list[i];
> +        label = virXPathStringLimit("string(./label)",
> +                                    VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
> +        def->seclabels[i]->label = label;
> +
> +        if (label && def->seclabels[i]->norelabel) {
>              virReportError(VIR_ERR_XML_ERROR,
> -                           _("invalid security relabel value %s"), p);
> -            VIR_FREE(p);
> -            VIR_FREE(*def);
> -            return -1;
> +                           _("Cannot specify a label if relabelling is "
> +                             "turned off. model=%s"),
> +                             def->seclabels[i]->model);
> +            goto error;
>          }
> -        VIR_FREE(p);
> -    } else {
> -        (*def)->norelabel = false;
>      }
> -
> -    p = virXPathStringLimit("string(./seclabel[1]/label[1])",
> -                            VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
> -    (*def)->label = p;
> -
> -    if ((*def)->label && (*def)->norelabel) {
> -        virReportError(VIR_ERR_XML_ERROR, "%s",
> -                       _("Cannot specify a label if relabelling is turned off"));
> -        VIR_FREE((*def)->label);
> -        VIR_FREE(*def);
> -        return -1;
> -    }
> -
> +    VIR_FREE(list);
>      return 0;
> +
> +error:
> +    for (i = 0; i < n; i++) {
> +        virSecurityDeviceLabelDefFree(def->seclabels[i]);
> +    }
> +    VIR_FREE(def->seclabels);
> +    VIR_FREE(list);
> +    return -1;
>  }
>  
>  
> @@ -3339,7 +3427,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
>                           xmlNodePtr node,
>                           xmlXPathContextPtr ctxt,
>                           virBitmapPtr bootMap,
> -                         virSecurityLabelDefPtr vmSeclabel,
> +                         virSecurityLabelDefPtr* vmSeclabels,
> +                         int nvmSeclabels,
>                           unsigned int flags)
>  {
>      virDomainDiskDefPtr def;
> @@ -3677,16 +3766,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
>      if (sourceNode) {
>          xmlNodePtr saved_node = ctxt->node;
>          ctxt->node = sourceNode;
> -        if ((VIR_ALLOC(def->seclabels) < 0) ||
> -            (VIR_ALLOC(def->seclabels[0]) < 0)) {
> -            virReportOOMError();
> -            goto error;
> -        }
> -        if (virSecurityDeviceLabelDefParseXML(&def->seclabels[0],
> -                                              vmSeclabel,
> +        if (virSecurityDeviceLabelDefParseXML(def, vmSeclabels,
> +                                              nvmSeclabels,
>                                                ctxt) < 0)
>              goto error;
> -        def->nseclabels = 1;
>          ctxt->node = saved_node;
>      }
>  
> @@ -7136,16 +7219,11 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
>          goto error;
>      }
>  
> -    if ((VIR_ALLOC(def->seclabels) < 0) ||
> -        (VIR_ALLOC(def->seclabels[0])) < 0 ) {
> -        virReportOOMError();
> -        goto error;
> -    }
> -
>      if (xmlStrEqual(node->name, BAD_CAST "disk")) {
>          dev->type = VIR_DOMAIN_DEVICE_DISK;
>          if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, ctxt,
> -                                                        NULL, def->seclabels[0],
> +                                                        NULL, def->seclabels,
> +                                                        def->nseclabels,
>                                                          flags)))
>              goto error;
>      } else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
> @@ -8084,13 +8162,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
>  
>      /* analysis of security label, done early even though we format it
>       * late, so devices can refer to this for defaults */
> -    if ((VIR_ALLOC(def->seclabels) < 0) ||
> -        (VIR_ALLOC(def->seclabels[0]) < 0)) {
> -        virReportOOMError();
> -        goto error;
> -    }
> -    def->nseclabels = 1;
> -    if (virSecurityLabelDefParseXML(def->seclabels[0], ctxt, flags) == -1)
> +    if (virSecurityLabelDefsParseXML(def, ctxt, flags) == -1)
>          goto error;
>  
>      /* Extract domain memory */
> @@ -8690,7 +8762,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
>                                                              nodes[i],
>                                                              ctxt,
>                                                              bootMap,
> -                                                            def->seclabels[0],
> +                                                            def->seclabels,
> +                                                            def->nseclabels,
>                                                              flags);
>          if (!disk)
>              goto error;
> @@ -11037,13 +11110,15 @@ virSecurityLabelDefFormat(virBufferPtr buf, virSecurityLabelDefPtr def)
>      virBufferAsprintf(buf, "<seclabel type='%s'",
>                        sectype);
>  
> +    if (def->model) {
> +        virBufferEscapeString(buf, " model='%s'", def->model);
> +    }
> +
>      if (def->type == VIR_DOMAIN_SECLABEL_NONE) {
>          virBufferAddLit(buf, "/>\n");
>          return;
>      }
>  
> -    virBufferEscapeString(buf, " model='%s'", def->model);
> -
>      virBufferAsprintf(buf, " relabel='%s'",
>                        def->norelabel ? "no" : "yes");
>  
> @@ -11069,8 +11144,8 @@ static void
>  virSecurityDeviceLabelDefFormat(virBufferPtr buf,
>                                  virSecurityDeviceLabelDefPtr def)
>  {
> -    virBufferAsprintf(buf, "<seclabel relabel='%s'",
> -                      def->norelabel ? "no" : "yes");
> +    virBufferAsprintf(buf, "<seclabel model='%s' relabel='%s'",
> +                      def->model, def->norelabel ? "no" : "yes");
>      if (def->label) {
>          virBufferAddLit(buf, ">\n");
>          virBufferEscapeString(buf, "  <label>%s</label>\n",
> @@ -11115,6 +11190,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
>      const char *copy_on_read = virDomainVirtioEventIdxTypeToString(def->copy_on_read);
>      const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
>  
> +    int n;
>      char uuidstr[VIR_UUID_STRING_BUFLEN];
>  
>      if (!type) {
> @@ -11210,10 +11286,11 @@ virDomainDiskDefFormat(virBufferPtr buf,
>              if (def->startupPolicy)
>                  virBufferEscapeString(buf, " startupPolicy='%s'",
>                                        startupPolicy);
> -            if (def->seclabels && def->seclabels[0]) {
> +            if (def->nseclabels) {
>                  virBufferAddLit(buf, ">\n");
>                  virBufferAdjustIndent(buf, 8);
> -                virSecurityDeviceLabelDefFormat(buf, def->seclabels[0]);
> +                for (n = 0; n < def->nseclabels; n++)
> +                    virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
>                  virBufferAdjustIndent(buf, -8);
>                  virBufferAddLit(buf, "      </source>\n");
>              } else {
> @@ -11223,10 +11300,11 @@ virDomainDiskDefFormat(virBufferPtr buf,
>          case VIR_DOMAIN_DISK_TYPE_BLOCK:
>              virBufferEscapeString(buf, "      <source dev='%s'",
>                                    def->src);
> -            if (def->seclabels && def->seclabels[0]) {
> +            if (def->nseclabels) {
>                  virBufferAddLit(buf, ">\n");
>                  virBufferAdjustIndent(buf, 8);
> -                virSecurityDeviceLabelDefFormat(buf, def->seclabels[0]);
> +                for (n = 0; n < def->nseclabels; n++)
> +                    virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
>                  virBufferAdjustIndent(buf, -8);
>                  virBufferAddLit(buf, "      </source>\n");
>              } else {
> @@ -13252,11 +13330,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
>  
>      virBufferAddLit(buf, "  </devices>\n");
>  
> -    if (def->nseclabels && def->seclabels) {
> -        virBufferAdjustIndent(buf, 2);
> -        virSecurityLabelDefFormat(buf, def->seclabels[0]);
> -        virBufferAdjustIndent(buf, -2);
> -    }
> +    virBufferAdjustIndent(buf, 2);
> +    for (n = 0; n < def->nseclabels; n++)
> +        virSecurityLabelDefFormat(buf, def->seclabels[n]);
> +    virBufferAdjustIndent(buf, -2);
>  
>      if (def->namespaceData && def->ns.format) {
>          if ((def->ns.format)(buf, def->namespaceData) < 0)
> @@ -15433,3 +15510,65 @@ cleanup:
>      VIR_FREE(xmlStr);
>      return ret;
>  }
> +
> +virSecurityLabelDefPtr
> +virDomainDefGetSecurityLabelDef(virDomainDefPtr def, const char *model)
> +{
> +    int i;
> +
> +    if (def == NULL || model == NULL)
> +        return NULL;
> +
> +    for (i = 0; i < def->nseclabels; i++) {
> +        if (def->seclabels[i]->model == NULL)
> +            continue;
> +        if (STREQ(def->seclabels[i]->model, model))
> +            return def->seclabels[i];
> +    }
> +
> +    return virDomainDefAddSecurityLabelDef(def, model);
> +}
> +
> +virSecurityDeviceLabelDefPtr
> +virDomainDiskDefGetSecurityLabelDef(virDomainDiskDefPtr def, const char *model)
> +{
> +    int i;
> +
> +    if (def == NULL)
> +        return NULL;
> +
> +    for (i = 0; i < def->nseclabels; i++) {
> +        if (STREQ(def->seclabels[i]->model, model))
> +            return def->seclabels[i];
> +    }
> +    return NULL;
> +}
> +
> +virSecurityLabelDefPtr
> +virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char *model)
> +{
> +    virSecurityLabelDefPtr seclabel = NULL;
> +
> +    if (VIR_ALLOC(seclabel) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    if (model) {
> +        seclabel->model = strdup(model);
> +        if (seclabel->model == NULL) {
> +            virReportOOMError();
> +            virSecurityLabelDefFree(seclabel);
> +            return NULL;
> +        }
> +    }
> +
> +    if (VIR_EXPAND_N(def->seclabels, def->nseclabels, 1) < 0) {
> +        virReportOOMError();
> +        virSecurityLabelDefFree(seclabel);
> +        return NULL;
> +    }
> +    def->seclabels[def->nseclabels - 1] = seclabel;
> +
> +    return seclabel;
> +}
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index db6ef6c..dda6d24 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -2161,6 +2161,15 @@ virDomainState
>  virDomainObjGetState(virDomainObjPtr obj, int *reason)
>          ATTRIBUTE_NONNULL(1);
>  
> +virSecurityLabelDefPtr
> +virDomainDefGetSecurityLabelDef(virDomainDefPtr def, const char *model);
> +
> +virSecurityDeviceLabelDefPtr
> +virDomainDiskDefGetSecurityLabelDef(virDomainDiskDefPtr def, const char *model);
> +
> +virSecurityLabelDefPtr
> +virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char *model);
> +
>  typedef const char* (*virLifecycleToStringFunc)(int type);
>  typedef int (*virLifecycleFromStringFunc)(const char *type);
>  
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 75997fe..be8b610 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -287,6 +287,9 @@ virDomainDefCompatibleDevice;
>  virDomainDefFormat;
>  virDomainDefFormatInternal;
>  virDomainDefFree;
> +virDomainDefGetSecurityLabelDef;
> +virDomainDiskDefGetSecurityLabelDef;
> +virDomainDefAddSecurityLabelDef;
>  virDomainDefParseFile;
>  virDomainDefParseNode;
>  virDomainDefParseString;
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-override.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-override.xml
> index 4de435b..426b663 100644
> --- a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-override.xml
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-override.xml
> @@ -16,14 +16,14 @@
>      <emulator>/usr/bin/qemu</emulator>
>      <disk type='block' device='disk'>
>        <source dev='/dev/HostVG/QEMUGuest1'>
> -        <seclabel relabel='no'/>
> +        <seclabel model='selinux' relabel='no'/>
>        </source>
>        <target dev='hda' bus='ide'/>
>        <address type='drive' controller='0' bus='0' target='0' unit='0'/>
>      </disk>
>      <disk type='block' device='disk'>
>        <source dev='/dev/HostVG/QEMUGuest2'>
> -        <seclabel relabel='yes'>
> +        <seclabel model='selinux' relabel='yes'>
>            <label>system_u:system_r:public_content_t:s0</label>
>          </seclabel>
>        </source>
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic.xml
> index 78a6b6a..36df9d4 100644
> --- a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic.xml
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic.xml
> @@ -22,5 +22,5 @@
>      <controller type='ide' index='0'/>
>      <memballoon model='virtio'/>
>    </devices>
> -  <seclabel type='dynamic' relabel='yes'/>
> +  <seclabel model='selinux' type='dynamic' relabel='yes'/>
>  </domain>
> 

ACK otherwise.

Michal




More information about the libvir-list mailing list