From: Rupesh Chiluka <[email protected]>

In raw datapath, iov builders copied application-supplied SG entries
into the fixed-size iov->src[]/dst[] stack buffers (max ROC_MAX_SG_CNT
entries) without validating the segment count. A raw-dp crypto vector
with more than ROC_MAX_SG_CNT segments results in a stack overwrite.

Reject vector lists whose src_sgl[].num, dest_sgl[].num, or n_data_vecs
exceed ROC_MAX_SG_CNT before copying.

cnxk_raw_burst_to_iov() and cnxk_raw_to_iov() now return an error,
which is propagated by the cn10k and cn20k raw enqueue paths to fail
the op cleanly.

Signed-off-by: Rupesh Chiluka <[email protected]>
---
 drivers/crypto/cnxk/cn10k_cryptodev_ops.c | 29 ++++++++++++++++++-----
 drivers/crypto/cnxk/cn20k_cryptodev_ops.c | 29 ++++++++++++++++++-----
 drivers/crypto/cnxk/cnxk_se.h             | 23 ++++++++++++++++--
 3 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/drivers/crypto/cnxk/cn10k_cryptodev_ops.c 
b/drivers/crypto/cnxk/cn10k_cryptodev_ops.c
index 870e65c049..bf273774fd 100644
--- a/drivers/crypto/cnxk/cn10k_cryptodev_ops.c
+++ b/drivers/crypto/cnxk/cn10k_cryptodev_ops.c
@@ -1615,17 +1615,30 @@ cn10k_cpt_raw_enqueue_burst(void *qpair, uint8_t 
*drv_ctx, struct rte_crypto_sym
                infl_req = &pend_q->req_queue[head];
                infl_req->op_flags = 0;
 
-               cnxk_raw_burst_to_iov(vec, &ofs, index, &iov);
+               ret = cnxk_raw_burst_to_iov(vec, &ofs, index, &iov);
+               if (unlikely(ret != 0)) {
+                       plt_dp_err("Failed to convert raw to iov: %d", index);
+                       if (i == 0 && count == 0) {
+                               *enqueue_status = ret;
+                               return 0;
+                       } else if (i == 0) {
+                               goto pend_q_commit;
+                       } else {
+                               break;
+                       }
+               }
                ret = cn10k_cpt_raw_fill_inst(&iov, qp, dp_ctx, &inst[i], 
infl_req,
                                              user_data[index], is_sgv2);
                if (unlikely(ret != 1)) {
                        plt_dp_err("Could not process vec: %d", index);
-                       if (i == 0 && count == 0)
-                               return -1;
-                       else if (i == 0)
+                       if (i == 0 && count == 0) {
+                               *enqueue_status = -EINVAL;
+                               return 0;
+                       } else if (i == 0) {
                                goto pend_q_commit;
-                       else
+                       } else {
                                break;
+                       }
                }
                pending_queue_advance(&head, pq_mask);
        }
@@ -1694,7 +1707,11 @@ cn10k_cpt_raw_enqueue(void *qpair, uint8_t *drv_ctx, 
struct rte_crypto_vec *data
        if (unlikely(nb_allowed == 0))
                return -1;
 
-       cnxk_raw_to_iov(data_vec, n_data_vecs, &ofs, iv, digest, 
aad_or_auth_iv, &iov);
+       ret = cnxk_raw_to_iov(data_vec, n_data_vecs, &ofs, iv, digest, 
aad_or_auth_iv, &iov);
+       if (unlikely(ret != 0)) {
+               plt_dp_err("Failed to convert raw to iov");
+               return -1;
+       }
 
        lmt_base = qp->lmtline.lmt_base;
        io_addr = qp->lmtline.io_addr;
diff --git a/drivers/crypto/cnxk/cn20k_cryptodev_ops.c 
b/drivers/crypto/cnxk/cn20k_cryptodev_ops.c
index a63b97654b..7707755775 100644
--- a/drivers/crypto/cnxk/cn20k_cryptodev_ops.c
+++ b/drivers/crypto/cnxk/cn20k_cryptodev_ops.c
@@ -1189,17 +1189,30 @@ cn20k_cpt_raw_enqueue_burst(void *qpair, uint8_t 
*drv_ctx, struct rte_crypto_sym
                infl_req = &pend_q->req_queue[head];
                infl_req->op_flags = 0;
 
-               cnxk_raw_burst_to_iov(vec, &ofs, index, &iov);
+               ret = cnxk_raw_burst_to_iov(vec, &ofs, index, &iov);
+               if (unlikely(ret != 0)) {
+                       plt_dp_err("Failed to convert raw to iov: %d", index);
+                       if (i == 0 && count == 0) {
+                               *enqueue_status = ret;
+                               return 0;
+                       } else if (i == 0) {
+                               goto pend_q_commit;
+                       } else {
+                               break;
+                       }
+               }
                ret = cn20k_cpt_raw_fill_inst(&iov, qp, dp_ctx, &inst[i], 
infl_req,
                                              user_data[index]);
                if (unlikely(ret != 1)) {
                        plt_dp_err("Could not process vec: %d", index);
-                       if (i == 0 && count == 0)
-                               return -1;
-                       else if (i == 0)
+                       if (i == 0 && count == 0) {
+                               *enqueue_status = -EINVAL;
+                               return 0;
+                       } else if (i == 0) {
                                goto pend_q_commit;
-                       else
+                       } else {
                                break;
+                       }
                }
                pending_queue_advance(&head, pq_mask);
        }
@@ -1249,7 +1262,11 @@ cn20k_cpt_raw_enqueue(void *qpair, uint8_t *drv_ctx, 
struct rte_crypto_vec *data
        if (unlikely(nb_allowed == 0))
                return -1;
 
-       cnxk_raw_to_iov(data_vec, n_data_vecs, &ofs, iv, digest, 
aad_or_auth_iv, &iov);
+       ret = cnxk_raw_to_iov(data_vec, n_data_vecs, &ofs, iv, digest, 
aad_or_auth_iv, &iov);
+       if (unlikely(ret != 0)) {
+               plt_dp_err("Failed to convert raw to iov");
+               return -1;
+       }
 
        lmt_base = qp->lmtline.lmt_base;
        io_addr = qp->lmtline.io_addr;
diff --git a/drivers/crypto/cnxk/cnxk_se.h b/drivers/crypto/cnxk/cnxk_se.h
index 505a5fcd37..b712acdccd 100644
--- a/drivers/crypto/cnxk/cnxk_se.h
+++ b/drivers/crypto/cnxk/cnxk_se.h
@@ -3633,10 +3633,19 @@ prepare_iov_from_raw_vec(struct rte_crypto_vec *vec, 
struct roc_se_iov_ptr *iove
        return total_len;
 }
 
-static __rte_always_inline void
+static __rte_always_inline int
 cnxk_raw_burst_to_iov(struct rte_crypto_sym_vec *vec, union rte_crypto_sym_ofs 
*ofs, int index,
                      struct cnxk_iov *iov)
 {
+       uint32_t dst_num =
+               (vec->dest_sgl == NULL) ? vec->src_sgl[index].num : 
vec->dest_sgl[index].num;
+
+       if (unlikely(vec->src_sgl[index].num > ROC_MAX_SG_CNT || dst_num > 
ROC_MAX_SG_CNT)) {
+               plt_dp_err("Number of segments (src: %u, dst: %u) exceeds max 
supported (%u)",
+                          vec->src_sgl[index].num, dst_num, ROC_MAX_SG_CNT);
+               return -ENOTSUP;
+       }
+
        iov->iv_buf = vec->iv[index].va;
        iov->aad_buf = vec->aad[index].va;
        iov->mac_buf = vec->digest[index].va;
@@ -3658,13 +3667,21 @@ cnxk_raw_burst_to_iov(struct rte_crypto_sym_vec *vec, 
union rte_crypto_sym_ofs *
 
        iov->a_head = ofs->ofs.auth.head;
        iov->a_tail = ofs->ofs.auth.tail;
+
+       return 0;
 }
 
-static __rte_always_inline void
+static __rte_always_inline int
 cnxk_raw_to_iov(struct rte_crypto_vec *data_vec, uint16_t n_vecs, union 
rte_crypto_sym_ofs *ofs,
                struct rte_crypto_va_iova_ptr *iv, struct 
rte_crypto_va_iova_ptr *digest,
                struct rte_crypto_va_iova_ptr *aad, struct cnxk_iov *iov)
 {
+       if (unlikely(n_vecs > ROC_MAX_SG_CNT)) {
+               plt_dp_err("Number of segments (%u) exceeds max supported 
(%u)", n_vecs,
+                          ROC_MAX_SG_CNT);
+               return -ENOTSUP;
+       }
+
        iov->iv_buf = iv->va;
        iov->aad_buf = aad->va;
        iov->mac_buf = digest->va;
@@ -3678,6 +3695,8 @@ cnxk_raw_to_iov(struct rte_crypto_vec *data_vec, uint16_t 
n_vecs, union rte_cryp
 
        iov->a_head = ofs->ofs.auth.head;
        iov->a_tail = ofs->ofs.auth.tail;
+
+       return 0;
 }
 
 static inline void
-- 
2.43.0

Reply via email to