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

