diff options
| author | Niall Meade <[email protected]> | 2024-09-30 13:40:02 +0000 |
|---|---|---|
| committer | Ferruh Yigit <[email protected]> | 2024-09-30 23:45:31 +0200 |
| commit | 30efe60d3a37896567b660229ef6a04c5526f6db (patch) | |
| tree | 549603e96a13cd7cb313483c8010a0769154f84f /lib/ethdev | |
| parent | a498019d793b3d5ae354a1a947b6bec3bd16fb5f (diff) | |
ethdev: fix overflow in descriptor count
Addressed a specific overflow issue in the eth_dev_adjust_nb_desc()
function where the uint16_t variable nb_desc would overflow when its
value was greater than (2^16 - nb_align). This overflow caused nb_desc
to incorrectly wrap around between 0 and nb_align-1, leading to the
function setting nb_desc to nb_min instead of the expected nb_max.
To give an example, let nb_desc=UINT16_MAX, nb_align=32, nb_max=4096 and
nb_min=64. RTE_ALIGN_CEIL(nb_desc, nb_align) calls
RTE_ALIGN_FLOOR(nb_desc + nb_align - 1, nb_align). This results in an
overflow of nb_desc, leading to nb_desc being set to 30 and then 0 when
the macros return. As a result of this, nb_desc is then set to nb_min
later on.
The resolution involves upcasting nb_desc to a uint32_t before the
RTE_ALIGN_CEIL macro is applied. This change ensures that the subsequent
call to RTE_ALIGN_FLOOR(nb_desc + (nb_align - 1), nb_align) does not
result in an overflow, as it would when nb_desc is a uint16_t. By using
a uint32_t for these operations, the correct behavior is maintained
without the risk of overflow.
Fixes: 0f67fc3baeb9 ("ethdev: add function to adjust number of descriptors")
Cc: [email protected]
Signed-off-by: Niall Meade <[email protected]>
Reviewed-by: Ferruh Yigit <[email protected]>
Diffstat (limited to 'lib/ethdev')
| -rw-r--r-- | lib/ethdev/rte_ethdev.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index a1f7efa913..84ee7588fc 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -6667,13 +6667,19 @@ static void eth_dev_adjust_nb_desc(uint16_t *nb_desc, const struct rte_eth_desc_lim *desc_lim) { + /* Upcast to uint32 to avoid potential overflow with RTE_ALIGN_CEIL(). */ + uint32_t nb_desc_32 = (uint32_t)*nb_desc; + if (desc_lim->nb_align != 0) - *nb_desc = RTE_ALIGN_CEIL(*nb_desc, desc_lim->nb_align); + nb_desc_32 = RTE_ALIGN_CEIL(nb_desc_32, desc_lim->nb_align); if (desc_lim->nb_max != 0) - *nb_desc = RTE_MIN(*nb_desc, desc_lim->nb_max); + nb_desc_32 = RTE_MIN(nb_desc_32, desc_lim->nb_max); + + nb_desc_32 = RTE_MAX(nb_desc_32, desc_lim->nb_min); - *nb_desc = RTE_MAX(*nb_desc, desc_lim->nb_min); + /* Assign clipped u32 back to u16. */ + *nb_desc = (uint16_t)nb_desc_32; } int |
