Hi > -----Original Message----- > From: Andrew Rybchenko <andrew.rybche...@oktetlabs.ru> > Sent: Friday, July 2, 2021 10:23 PM > To: Matan Azrad <ma...@nvidia.com>; Shahaf Shuler <shah...@nvidia.com>; Slava > Ovsiienko <viachesl...@nvidia.com>; NBU- > Contact-Thomas Monjalon <tho...@monjalon.net>; Ferruh Yigit > <ferruh.yi...@intel.com>; Xueming(Steven) Li > <xuemi...@nvidia.com> > Cc: dev@dpdk.org; Viacheslav Galaktionov > <viacheslav.galaktio...@oktetlabs.ru>; sta...@dpdk.org > Subject: [PATCH] ethdev: keep count of allocated and used representor ranges > > From: Viacheslav Galaktionov <viacheslav.galaktio...@oktetlabs.ru> > > In its current state, the API can overflow the user-passed buffer if a new > representor range appears between function calls. > > In order to solve this problem, augment the representor info structure with > the numbers of allocated and initialized ranges. This way > the users of this structure can be sure they will not overrun the buffer.
Thanks for making this api more robust! > > Fixes: 85e1588ca72f ("ethdev: add API to get representor info") > Cc: sta...@dpdk.org > > Signed-off-by: Viacheslav Galaktionov <viacheslav.galaktio...@oktetlabs.ru> > Signed-off-by: Andrew Rybchenko <andrew.rybche...@oktetlabs.ru> > --- > drivers/net/mlx5/mlx5_ethdev.c | 15 +++++++++++++++ > lib/ethdev/rte_ethdev.c | 6 ++++-- > lib/ethdev/rte_ethdev.h | 9 ++++++++- > 3 files changed, 27 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c > index 90baee5aa4..61b1c0e75c 100644 > --- a/drivers/net/mlx5/mlx5_ethdev.c > +++ b/drivers/net/mlx5/mlx5_ethdev.c > @@ -413,9 +413,15 @@ mlx5_representor_info_get(struct rte_eth_dev *dev, > int n_type = 4; /* Representor types, VF, HPF@VF, SF and HPF@SF. */ > int n_pf = 2; /* Number of PFs. */ > int i = 0, pf; > + int n_entries; > > if (info == NULL) > goto out; > + > + n_entries = n_type * n_pf; > + if ((uint32_t)n_entries > info->nb_ranges_alloc) > + n_entries = info->nb_ranges_alloc; > + > info->controller = 0; > info->pf = priv->pf_bond >= 0 ? priv->pf_bond : 0; > for (pf = 0; pf < n_pf; ++pf) { > @@ -431,6 +437,8 @@ mlx5_representor_info_get(struct rte_eth_dev *dev, > snprintf(info->ranges[i].name, > sizeof(info->ranges[i].name), "pf%dvf", pf); > i++; > + if (i == n_entries) > + break; > /* HPF range of VF type. */ > info->ranges[i].type = RTE_ETH_REPRESENTOR_VF; > info->ranges[i].controller = 0; > @@ -443,6 +451,8 @@ mlx5_representor_info_get(struct rte_eth_dev *dev, > snprintf(info->ranges[i].name, > sizeof(info->ranges[i].name), "pf%dvf", pf); > i++; > + if (i == n_entries) > + break; > /* SF range. */ > info->ranges[i].type = RTE_ETH_REPRESENTOR_SF; > info->ranges[i].controller = 0; > @@ -455,6 +465,8 @@ mlx5_representor_info_get(struct rte_eth_dev *dev, > snprintf(info->ranges[i].name, > sizeof(info->ranges[i].name), "pf%dsf", pf); > i++; > + if (i == n_entries) > + break; > /* HPF range of SF type. */ > info->ranges[i].type = RTE_ETH_REPRESENTOR_SF; > info->ranges[i].controller = 0; > @@ -467,8 +479,11 @@ mlx5_representor_info_get(struct rte_eth_dev *dev, > snprintf(info->ranges[i].name, > sizeof(info->ranges[i].name), "pf%dsf", pf); > i++; > + if (i == n_entries) > + break; > } > out: > + info->nb_ranges = i; Here info maybe NULL. > return n_type * n_pf; > } > > diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index > c607eabb5b..30abc93b18 100644 > --- a/lib/ethdev/rte_ethdev.c > +++ b/lib/ethdev/rte_ethdev.c > @@ -5987,7 +5987,8 @@ rte_eth_representor_id_get(const struct rte_eth_dev > *ethdev, > int controller, int pf, int representor_port, > uint16_t *repr_id) > { > - int ret, n, i, count; > + int ret, n, count; > + uint32_t i; > struct rte_eth_representor_info *info = NULL; > size_t size; > > @@ -6011,6 +6012,7 @@ rte_eth_representor_id_get(const struct rte_eth_dev > *ethdev, > info = calloc(1, size); > if (info == NULL) > return -ENOMEM; > + info->nb_ranges_alloc = n; > ret = rte_eth_representor_info_get(ethdev->data->port_id, info); > if (ret < 0) > goto out; > @@ -6023,7 +6025,7 @@ rte_eth_representor_id_get(const struct rte_eth_dev > *ethdev, > > /* Locate representor ID. */ > ret = -ENOENT; > - for (i = 0; i < n; ++i) { > + for (i = 0; i < info->nb_ranges; ++i) { > if (info->ranges[i].type != type) > continue; > if (info->ranges[i].controller != controller) diff --git > a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h index > faf3bd901d..d2b27c351f 100644 > --- a/lib/ethdev/rte_ethdev.h > +++ b/lib/ethdev/rte_ethdev.h > @@ -4856,6 +4856,8 @@ struct rte_eth_representor_range { struct > rte_eth_representor_info { > uint16_t controller; /**< Controller ID of caller device. */ > uint16_t pf; /**< Physical function ID of caller device. */ > + uint32_t nb_ranges_alloc; /**< Size of the ranges array. */ > + uint32_t nb_ranges; /**< Number of initialized ranges. */ How about rte_eth_representor_info_get(info) return max ranges size if info is NULL, return real initialized ranges if info not NULL? > struct rte_eth_representor_range ranges[];/**< Representor ID range. */ > }; > > @@ -4871,11 +4873,16 @@ struct rte_eth_representor_info { > * A pointer to a representor info structure. > * NULL to return number of range entries and allocate memory > * for next call to store detail. > + * The number of ranges that were written into this structure > + * will be placed into its nb_ranges field. This number cannot be > + * larger than the nb_ranges_alloc that by the user before calling > + * this function. It can be smaller than the value returned by the > + * function, however. > * @return > * - (-ENOTSUP) if operation is not supported. > * - (-ENODEV) if *port_id* invalid. > * - (-EIO) if device is removed. > - * - (>=0) number of representor range entries supported by device. > + * - (>=0) number of available representor range entries. > */ > __rte_experimental > int rte_eth_representor_info_get(uint16_t port_id, > -- > 2.30.2