summaryrefslogtreecommitdiff
path: root/lib/ethdev
diff options
context:
space:
mode:
authorNiall Meade <[email protected]>2024-09-30 13:40:02 +0000
committerFerruh Yigit <[email protected]>2024-09-30 23:45:31 +0200
commit30efe60d3a37896567b660229ef6a04c5526f6db (patch)
tree549603e96a13cd7cb313483c8010a0769154f84f /lib/ethdev
parenta498019d793b3d5ae354a1a947b6bec3bd16fb5f (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.c12
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