nix_tm_copy_rsp_to_nix() consumes the txsch alloc response verbatim.
The count rsp->schq[lvl] is not bounded to the 128-entry list, so a
large count over-reads schq_list[lvl][]; and the schq id is passed
to plt_bitmap_set() as the bit position without checking it against
NIX_TM_MAX_HW_TXSCHQ (2048). rte_bitmap_set() does not bound-check
pos, so an id >= 2048 writes outside the bitmap and corrupts memory.

Clamp the count to MAX_TXSCHQ_PER_FUNC and reject any id >=
NIX_TM_MAX_HW_TXSCHQ with -EINVAL, propagating the error out of
nix_tm_alloc_txschq() so setup fails cleanly. Applied to both the
discontiguous and contiguous lists.

Fixes: df405df95eeb ("common/cnxk: add NIX TM helper to alloc/free resource")
Cc: [email protected]

Signed-off-by: Aarnav JP <[email protected]>
---
 drivers/common/cnxk/roc_nix_priv.h   |  2 +-
 drivers/common/cnxk/roc_nix_tm.c     | 37 ++++++++++++++++++++++------
 drivers/common/cnxk/roc_nix_tm_ops.c |  8 ++++--
 3 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/common/cnxk/roc_nix_priv.h 
b/drivers/common/cnxk/roc_nix_priv.h
index d4b3c7c1af..9779b336b0 100644
--- a/drivers/common/cnxk/roc_nix_priv.h
+++ b/drivers/common/cnxk/roc_nix_priv.h
@@ -421,7 +421,7 @@ int nix_tm_alloc_txschq(struct nix *nix, enum 
roc_nix_tm_tree tree);
 int nix_tm_assign_resources(struct nix *nix, enum roc_nix_tm_tree tree);
 int nix_tm_release_resources(struct nix *nix, uint8_t hw_lvl, bool contig,
                             bool above_thresh);
-void nix_tm_copy_rsp_to_nix(struct nix *nix, struct nix_txsch_alloc_rsp *rsp);
+int nix_tm_copy_rsp_to_nix(struct nix *nix, struct nix_txsch_alloc_rsp *rsp);
 
 int nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree);
 int nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree);
diff --git a/drivers/common/cnxk/roc_nix_tm.c b/drivers/common/cnxk/roc_nix_tm.c
index 76c0f01884..2f38b042f9 100644
--- a/drivers/common/cnxk/roc_nix_tm.c
+++ b/drivers/common/cnxk/roc_nix_tm.c
@@ -1483,21 +1483,40 @@ nix_tm_assign_resources(struct nix *nix, enum 
roc_nix_tm_tree tree)
        return 0;
 }
 
-void
+int
 nix_tm_copy_rsp_to_nix(struct nix *nix, struct nix_txsch_alloc_rsp *rsp)
 {
        uint8_t lvl;
        uint16_t i;
 
        for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
-               for (i = 0; i < rsp->schq[lvl]; i++)
-                       plt_bitmap_set(nix->schq_bmp[lvl],
-                                      rsp->schq_list[lvl][i]);
 
-               for (i = 0; i < rsp->schq_contig[lvl]; i++)
-                       plt_bitmap_set(nix->schq_contig_bmp[lvl],
-                                      rsp->schq_contig_list[lvl][i]);
+               uint16_t cnt = PLT_MIN(rsp->schq[lvl], 
(uint16_t)MAX_TXSCHQ_PER_FUNC);
+
+               for (i = 0; i < cnt; i++) {
+                       uint16_t id = rsp->schq_list[lvl][i];
+
+                       if (id >= NIX_TM_MAX_HW_TXSCHQ) {
+                               plt_err("Invalid schq %u for lvl %u in alloc 
rsp", id, lvl);
+                               return -EINVAL;
+                       }
+                       plt_bitmap_set(nix->schq_bmp[lvl], id);
+               }
+
+               cnt = PLT_MIN(rsp->schq_contig[lvl], 
(uint16_t)MAX_TXSCHQ_PER_FUNC);
+
+               for (i = 0; i < cnt; i++) {
+                       uint16_t id = rsp->schq_contig_list[lvl][i];
+
+                       if (id >= NIX_TM_MAX_HW_TXSCHQ) {
+                               plt_err("Invalid contig schq %u for lvl %u in 
alloc rsp", id, lvl);
+                               return -EINVAL;
+                       }
+                       plt_bitmap_set(nix->schq_contig_bmp[lvl], id);
+               }
        }
+
+       return 0;
 }
 
 int
@@ -1563,8 +1582,10 @@ nix_tm_alloc_txschq(struct nix *nix, enum 
roc_nix_tm_tree tree)
                        goto alloc_err;
                }
 
-               nix_tm_copy_rsp_to_nix(nix, rsp);
+               rc = nix_tm_copy_rsp_to_nix(nix, rsp);
                mbox_put(mbox);
+               if (rc)
+                       goto alloc_err;
        } while (pend);
 
        nix->tm_link_cfg_lvl = rsp->link_cfg_lvl;
diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c 
b/drivers/common/cnxk/roc_nix_tm_ops.c
index 230e9b72f6..1086f471e6 100644
--- a/drivers/common/cnxk/roc_nix_tm_ops.c
+++ b/drivers/common/cnxk/roc_nix_tm_ops.c
@@ -778,8 +778,10 @@ roc_nix_tm_prealloc_res(struct roc_nix *roc_nix, uint8_t 
lvl,
                        return rc;
                }
 
-               nix_tm_copy_rsp_to_nix(nix, rsp);
+               rc = nix_tm_copy_rsp_to_nix(nix, rsp);
                mbox_put(mbox);
+               if (rc)
+                       return rc;
        }
 
        /* Preallocate contiguous */
@@ -797,8 +799,10 @@ roc_nix_tm_prealloc_res(struct roc_nix *roc_nix, uint8_t 
lvl,
                        return rc;
                }
 
-               nix_tm_copy_rsp_to_nix(nix, rsp);
+               rc = nix_tm_copy_rsp_to_nix(nix, rsp);
                mbox_put(mbox);
+               if (rc)
+                       return rc;
        }
 
        /* Save thresholds */
-- 
2.43.0

Reply via email to