[libvirt PATCH 4/7] nodedev: Add parser validation for node devices

Michal Prívozník mprivozn at redhat.com
Mon Jul 26 14:47:02 UTC 2021


On 7/23/21 6:40 PM, Jonathon Jongsma wrote:
> At the moment, this is only for mediated devices. When a new mediated
> device is created or defined, the xml is expected specify the nodedev
> name of an existing device as its parent. We were not previously
> validating this and were simply accepting any string here.
> 
> Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
> ---
>  src/conf/node_device_conf.c          | 30 +++++++++---
>  src/conf/node_device_conf.h          | 20 +++++++-
>  src/conf/virnodedeviceobj.h          |  1 +
>  src/hypervisor/domain_driver.c       |  7 +--
>  src/node_device/node_device_driver.c | 68 +++++++++++++++++++++++++++-
>  src/node_device/node_device_driver.h |  3 ++
>  src/node_device/node_device_udev.c   |  2 +
>  src/test/test_driver.c               |  6 ++-
>  tests/nodedevmdevctltest.c           |  7 ++-
>  tests/nodedevxml2xmltest.c           |  3 +-
>  10 files changed, 129 insertions(+), 18 deletions(-)
> 
> diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
> index 332b12f997..cd1c07092d 100644
> --- a/src/conf/node_device_conf.c
> +++ b/src/conf/node_device_conf.c
> @@ -2174,10 +2174,12 @@ static virNodeDeviceDef *
>  virNodeDeviceDefParse(const char *str,
>                        const char *filename,
>                        int create,
> -                      const char *virt_type)
> +                      const char *virt_type,
> +                      virNodeDeviceDefParserCallbacks *parserCallbacks,
> +                      void *opaque)
>  {
>      xmlDocPtr xml;
> -    virNodeDeviceDef *def = NULL;
> +    g_autoptr(virNodeDeviceDef) def = NULL;
>  
>      if ((xml = virXMLParse(filename, str, _("(node_device_definition)")))) {
>          def = virNodeDeviceDefParseNode(xml, xmlDocGetRootElement(xml),
> @@ -2185,25 +2187,39 @@ virNodeDeviceDefParse(const char *str,
>          xmlFreeDoc(xml);
>      }
>  
> -    return def;
> +    if (parserCallbacks) {
> +        int ret = 0;
> +        /* validate definition */
> +        if (parserCallbacks->validate) {
> +            ret = parserCallbacks->validate(def, opaque);
> +            if (ret < 0)
> +                return NULL;

Or simply without the @ret variable:

if (parserCallbacks->validate &&
    parserCallbacks->validate(def, opaque) < 0)
    return NULL;

Maybe even a direct call of the ->validate() callback is sufficient
because looking into the future there's not a case where parserCallbacks
!= NULL but ->validate == NULL; or is there?

> +        }
> +    }
> +
> +    return g_steal_pointer(&def);
>  }
>  
>  
>  virNodeDeviceDef *
>  virNodeDeviceDefParseString(const char *str,
>                              int create,
> -                            const char *virt_type)
> +                            const char *virt_type,
> +                            virNodeDeviceDefParserCallbacks *parserCallbacks,
> +                            void *opaque)
>  {
> -    return virNodeDeviceDefParse(str, NULL, create, virt_type);
> +    return virNodeDeviceDefParse(str, NULL, create, virt_type, parserCallbacks, opaque);
>  }
>  
>  
>  virNodeDeviceDef *
>  virNodeDeviceDefParseFile(const char *filename,
>                            int create,
> -                          const char *virt_type)
> +                          const char *virt_type,
> +                          virNodeDeviceDefParserCallbacks *parserCallbacks,
> +                          void *opaque)
>  {
> -    return virNodeDeviceDefParse(NULL, filename, create, virt_type);
> +    return virNodeDeviceDefParse(NULL, filename, create, virt_type, parserCallbacks, opaque);
>  }
>  
>  
> diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
> index 556878b9a8..786de85060 100644
> --- a/src/conf/node_device_conf.h
> +++ b/src/conf/node_device_conf.h
> @@ -349,15 +349,31 @@ struct _virNodeDeviceDef {
>  char *
>  virNodeDeviceDefFormat(const virNodeDeviceDef *def);
>  
> +
> +typedef int (*virNodeDeviceDefPostParseCallback)(virNodeDeviceDef *dev,
> +                                                 void *opaque);
> +
> +typedef int (*virNodeDeviceDefValidateCallback)(virNodeDeviceDef *dev,
> +                                                void *opaque);
> +
> +typedef struct _virNodeDeviceDefParserCallbacks {
> +    virNodeDeviceDefPostParseCallback postParse;
> +    virNodeDeviceDefValidateCallback validate;
> +} virNodeDeviceDefParserCallbacks;
> +
>  virNodeDeviceDef *
>  virNodeDeviceDefParseString(const char *str,
>                              int create,
> -                            const char *virt_type);
> +                            const char *virt_type,
> +                            virNodeDeviceDefParserCallbacks *callbacks,
> +                            void *opaque);
>  
>  virNodeDeviceDef *
>  virNodeDeviceDefParseFile(const char *filename,
>                            int create,
> -                          const char *virt_type);
> +                          const char *virt_type,
> +                          virNodeDeviceDefParserCallbacks *callbacks,
> +                          void *opaque);
>  
>  virNodeDeviceDef *
>  virNodeDeviceDefParseNode(xmlDocPtr xml,
> diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h
> index 0cb78748a4..1fdd4f65da 100644
> --- a/src/conf/virnodedeviceobj.h
> +++ b/src/conf/virnodedeviceobj.h
> @@ -47,6 +47,7 @@ struct _virNodeDeviceDriverState {
>  
>      /* Immutable pointer, self-locking APIs */
>      virObjectEventState *nodeDeviceEventState;
> +    virNodeDeviceDefParserCallbacks parserCallbacks;
>  };
>  
>  void
> diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
> index 29e11c0447..2969d55173 100644
> --- a/src/hypervisor/domain_driver.c
> +++ b/src/hypervisor/domain_driver.c
> @@ -395,7 +395,8 @@ virDomainDriverNodeDeviceReset(virNodeDevicePtr dev,
>      if (!xml)
>          return -1;
>  
> -    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
> +    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL,
> +                                      NULL, NULL);
>      if (!def)
>          return -1;
>  
> @@ -440,7 +441,7 @@ virDomainDriverNodeDeviceReAttach(virNodeDevicePtr dev,
>      if (!xml)
>          return -1;
>  
> -    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
> +    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL, NULL, NULL);
>      if (!def)
>          return -1;
>  
> @@ -488,7 +489,7 @@ virDomainDriverNodeDeviceDetachFlags(virNodeDevicePtr dev,
>      if (!xml)
>          return -1;
>  
> -    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
> +    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL, NULL, NULL);
>      if (!def)
>          return -1;
>  
> diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
> index ad2ca2a614..8f39d79c68 100644
> --- a/src/node_device/node_device_driver.c
> +++ b/src/node_device/node_device_driver.c
> @@ -896,7 +896,8 @@ nodeDeviceCreateXML(virConnectPtr conn,
>  
>      virt_type  = virConnectGetType(conn);
>  
> -    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type)))
> +    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type,
> +                                            &driver->parserCallbacks, NULL)))
>          return NULL;
>  
>      if (virNodeDeviceCreateXMLEnsureACL(conn, def) < 0)
> @@ -1376,7 +1377,8 @@ nodeDeviceDefineXML(virConnect *conn,
>  
>      virt_type  = virConnectGetType(conn);
>  
> -    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type)))
> +    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type,
> +                                            &driver->parserCallbacks, NULL)))
>          return NULL;
>  
>      if (virNodeDeviceDefineXMLEnsureACL(conn, def) < 0)
> @@ -1761,3 +1763,65 @@ nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
>  
>      return ret;
>  }
> +
> +
> +/* validate that parent exists */
> +static int nodeDeviceDefValidateMdev(virNodeDeviceDef *def,
> +                                     G_GNUC_UNUSED virNodeDevCapMdev *mdev,
> +                                     G_GNUC_UNUSED void *opaque)
> +{
> +    virNodeDeviceObj *obj = NULL;
> +    if (!def->parent) {

Here and elsewhere in the series - please separate these two blocks with
an empty line:

virNodeDeviceObj *obj = NULL;

if (!def->parent)
  ...

> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("missing parent device"));
> +        return -1;
> +    }
> +    obj = virNodeDeviceObjListFindByName(driver->devs, def->parent);
> +    if (!obj) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("invalid parent device '%s'"),
> +                       def->parent);
> +        return -1;
> +    }
> +
> +    virNodeDeviceObjEndAPI(&obj);
> +    return 0;
> +}
> +

Michal




More information about the libvir-list mailing list