From: Rupesh Chiluka <[email protected]>

prepare_iov_from_pkt() and prepare_iov_from_pkt_inplace() wrote one
iovec->bufs[] entry per mbuf segment with no bound check, overflowing
the fixed-size stack buffer (capacity ROC_MAX_SG_CNT) on the lookaside
symmetric path.

Reject segment counts exceeding ROC_MAX_SG_CNT in both builders and
fail the op.

Signed-off-by: Rupesh Chiluka <[email protected]>
---
 drivers/crypto/cnxk/cnxk_se.h | 51 ++++++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/cnxk/cnxk_se.h b/drivers/crypto/cnxk/cnxk_se.h
index b712acdccd..a3c3c3ce86 100644
--- a/drivers/crypto/cnxk/cnxk_se.h
+++ b/drivers/crypto/cnxk/cnxk_se.h
@@ -2670,6 +2670,7 @@ prepare_iov_from_pkt(struct rte_mbuf *pkt, struct 
roc_se_iov_ptr *iovec, uint32_
                     const bool is_aead, const bool is_sg_ver2)
 {
        uint16_t index = 0;
+       uint16_t nb_segs = 0;
        void *seg_data = NULL;
        int32_t seg_size = 0;
 
@@ -2678,6 +2679,8 @@ prepare_iov_from_pkt(struct rte_mbuf *pkt, struct 
roc_se_iov_ptr *iovec, uint32_
                return 0;
        }
 
+       nb_segs = pkt->nb_segs;
+
        if (!start_offset) {
                seg_data = rte_pktmbuf_mtod(pkt, void *);
                seg_size = pkt->data_len;
@@ -2685,6 +2688,12 @@ prepare_iov_from_pkt(struct rte_mbuf *pkt, struct 
roc_se_iov_ptr *iovec, uint32_
                while (start_offset >= pkt->data_len) {
                        start_offset -= pkt->data_len;
                        pkt = pkt->next;
+                       nb_segs--;
+
+                       if (unlikely(pkt == NULL)) {
+                               plt_dp_err("Start offset beyond end of packet");
+                               return 1;
+                       }
                }
 
                seg_data = rte_pktmbuf_mtod_offset(pkt, void *, start_offset);
@@ -2693,6 +2702,12 @@ prepare_iov_from_pkt(struct rte_mbuf *pkt, struct 
roc_se_iov_ptr *iovec, uint32_
                        return 1;
        }
 
+       if (unlikely(nb_segs > ROC_MAX_SG_CNT)) {
+               plt_dp_err("Number of segments (%u) exceeds max supported 
(%u)", nb_segs,
+                          ROC_MAX_SG_CNT);
+               return 1;
+       }
+
        /* first seg */
        iovec->bufs[index].vaddr = seg_data;
        iovec->bufs[index].size = seg_size;
@@ -2717,7 +2732,7 @@ prepare_iov_from_pkt(struct rte_mbuf *pkt, struct 
roc_se_iov_ptr *iovec, uint32_
        return 0;
 }
 
-static __rte_always_inline void
+static __rte_always_inline uint32_t
 prepare_iov_from_pkt_inplace(struct rte_mbuf *pkt,
                             struct roc_se_fc_params *param, uint32_t *flags)
 {
@@ -2726,6 +2741,12 @@ prepare_iov_from_pkt_inplace(struct rte_mbuf *pkt,
        uint32_t seg_size = 0;
        struct roc_se_iov_ptr *iovec;
 
+       if (unlikely(pkt->nb_segs > ROC_MAX_SG_CNT)) {
+               plt_dp_err("Number of segments (%u) exceeds max supported 
(%u)", pkt->nb_segs,
+                          ROC_MAX_SG_CNT);
+               return 1;
+       }
+
        seg_data = rte_pktmbuf_mtod(pkt, void *);
        seg_size = pkt->data_len;
 
@@ -2740,7 +2761,7 @@ prepare_iov_from_pkt_inplace(struct rte_mbuf *pkt,
 
                param->bufs[0].vaddr = seg_data;
                param->bufs[0].size = seg_size;
-               return;
+               return 0;
        }
        iovec = param->src_iov;
        iovec->bufs[index].vaddr = seg_data;
@@ -2764,7 +2785,7 @@ prepare_iov_from_pkt_inplace(struct rte_mbuf *pkt,
        }
 
        iovec->buf_cnt = index;
-       return;
+       return 0;
 }
 
 static __rte_always_inline int
@@ -2816,7 +2837,11 @@ fill_sm_params(struct rte_crypto_op *cop, struct 
cnxk_se_sess *sess,
 
        if (m_dst == NULL) {
                fc_params.dst_iov = fc_params.src_iov = (void *)src;
-               prepare_iov_from_pkt_inplace(m_src, &fc_params, &flags);
+               if (unlikely(prepare_iov_from_pkt_inplace(m_src, &fc_params, 
&flags))) {
+                       plt_dp_err("Prepare inplace src iov failed");
+                       ret = -EINVAL;
+                       goto err_exit;
+               }
        } else {
                /* Out of place processing */
                fc_params.src_iov = (void *)src;
@@ -3017,7 +3042,11 @@ fill_fc_params(struct rte_crypto_op *cop, struct 
cnxk_se_sess *sess,
                 */
                fc_params.dst_iov = fc_params.src_iov = (void *)src;
 
-               prepare_iov_from_pkt_inplace(m_src, &fc_params, &flags);
+               if (unlikely(prepare_iov_from_pkt_inplace(m_src, &fc_params, 
&flags))) {
+                       plt_dp_err("Prepare inplace src iov failed");
+                       ret = -EINVAL;
+                       goto err_exit;
+               }
 
        } else {
                /* Out of place processing */
@@ -3165,7 +3194,11 @@ fill_pdcp_params(struct rte_crypto_op *cop, struct 
cnxk_se_sess *sess,
 
        if (likely(m_dst == NULL || m_src == m_dst)) {
                fc_params.dst_iov = fc_params.src_iov = (void *)src;
-               prepare_iov_from_pkt_inplace(m_src, &fc_params, &flags);
+               if (unlikely(prepare_iov_from_pkt_inplace(m_src, &fc_params, 
&flags))) {
+                       plt_dp_err("Prepare inplace src iov failed");
+                       ret = -EINVAL;
+                       goto err_exit;
+               }
        } else {
                /* Out of place processing */
 
@@ -3298,7 +3331,11 @@ fill_pdcp_chain_params(struct rte_crypto_op *cop, struct 
cnxk_se_sess *sess,
 
        if (likely((m_dst == NULL || m_dst == m_src)) && inplace) {
                fc_params.dst_iov = fc_params.src_iov = (void *)src;
-               prepare_iov_from_pkt_inplace(m_src, &fc_params, &flags);
+               if (unlikely(prepare_iov_from_pkt_inplace(m_src, &fc_params, 
&flags))) {
+                       plt_dp_err("Could not prepare inplace src iov");
+                       ret = -EINVAL;
+                       goto err_exit;
+               }
        } else {
                /* Out of place processing */
                fc_params.src_iov = (void *)src;
-- 
2.43.0

Reply via email to