diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c index e3ae8ea36fba..d32d651530bb 100644 --- a/drivers/infiniband/hw/irdma/verbs.c +++ b/drivers/infiniband/hw/irdma/verbs.c @@ -1299,7 +1299,6 @@ static int irdma_wait_for_suspend(struct irdma_qp *iwqp) int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { -#define IRDMA_MODIFY_QP_MIN_REQ_LEN offsetofend(struct irdma_modify_qp_req, rq_flush) #define IRDMA_MODIFY_QP_MIN_RESP_LEN offsetofend(struct irdma_modify_qp_resp, push_valid) struct irdma_pd *iwpd = to_iwpd(ibqp->pd); struct irdma_qp *iwqp = to_iwqp(ibqp); @@ -1326,9 +1325,15 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (udata) { /* udata inlen/outlen can be 0 when supporting legacy libi40iw */ - if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) || - (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN)) + if (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN) return -EINVAL; + + /* For current irdma, validate against ABI def. */ + if (udata->inlen) { + ret = ib_copy_validate_udata_in(udata, ureq, rsvd); + if (ret) + return ret; + } } if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS) @@ -1571,10 +1576,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, iwqp->ibqp_state = attr->qp_state; spin_unlock_irqrestore(&iwqp->lock, flags); if (udata && udata->inlen) { - if (ib_copy_from_udata(&ureq, udata, - min(sizeof(ureq), udata->inlen))) - return -EINVAL; - irdma_flush_wqes(iwqp, (ureq.sq_flush ? IRDMA_FLUSH_SQ : 0) | (ureq.rq_flush ? IRDMA_FLUSH_RQ : 0) | @@ -1664,7 +1665,6 @@ exit: int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { -#define IRDMA_MODIFY_QP_MIN_REQ_LEN offsetofend(struct irdma_modify_qp_req, rq_flush) #define IRDMA_MODIFY_QP_MIN_RESP_LEN offsetofend(struct irdma_modify_qp_resp, push_valid) struct irdma_qp *iwqp = to_iwqp(ibqp); struct irdma_device *iwdev = iwqp->iwdev; @@ -1686,9 +1686,14 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, if (udata) { /* udata inlen/outlen can be 0 when supporting legacy libi40iw */ - if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) || - (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN)) + if (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN) return -EINVAL; + + if (udata->inlen) { + err = ib_copy_validate_udata_in(udata, ureq, rsvd); + if (err) + return err; + } } if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS) @@ -1778,10 +1783,6 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, iwqp->ibqp_state = attr->qp_state; spin_unlock_irqrestore(&iwqp->lock, flags); if (udata && udata->inlen) { - if (ib_copy_from_udata(&ureq, udata, - min(sizeof(ureq), udata->inlen))) - return -EINVAL; - irdma_flush_wqes(iwqp, (ureq.sq_flush ? IRDMA_FLUSH_SQ : 0) | (ureq.rq_flush ? IRDMA_FLUSH_RQ : 0) | @@ -2073,7 +2074,6 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata) static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries, struct ib_udata *udata) { -#define IRDMA_RESIZE_CQ_MIN_REQ_LEN offsetofend(struct irdma_resize_cq_req, user_cq_buffer) struct irdma_cq *iwcq = to_iwcq(ibcq); struct irdma_sc_dev *dev = iwcq->sc_cq.dev; struct irdma_cqp_request *cqp_request; @@ -2097,9 +2097,6 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries, IRDMA_FEATURE_CQ_RESIZE)) return -EOPNOTSUPP; - if (udata && udata->inlen < IRDMA_RESIZE_CQ_MIN_REQ_LEN) - return -EINVAL; - if (entries > rf->max_cqe) return -EINVAL; @@ -2133,9 +2130,9 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries, rdma_udata_to_drv_context(udata, struct irdma_ucontext, ibucontext); - if (ib_copy_from_udata(&req, udata, - min(sizeof(req), udata->inlen))) - return -EINVAL; + ret = ib_copy_validate_udata_in(udata, req, user_cq_buffer); + if (ret) + return ret; spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags); iwpbl_buf = irdma_get_pbl((unsigned long)req.user_cq_buffer, @@ -2327,24 +2324,20 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev, struct irdma_srq_init_info *info, struct ib_udata *udata) { -#define IRDMA_CREATE_SRQ_MIN_REQ_LEN \ - offsetofend(struct irdma_create_srq_req, user_shadow_area) struct irdma_create_srq_req req = {}; struct irdma_ucontext *ucontext; struct irdma_srq_mr *srqmr; struct irdma_pbl *iwpbl; unsigned long flags; + int ret; iwsrq->user_mode = true; ucontext = rdma_udata_to_drv_context(udata, struct irdma_ucontext, ibucontext); - if (udata->inlen < IRDMA_CREATE_SRQ_MIN_REQ_LEN) - return -EINVAL; - - if (ib_copy_from_udata(&req, udata, - min(sizeof(req), udata->inlen))) - return -EFAULT; + ret = ib_copy_validate_udata_in(udata, req, user_shadow_area); + if (ret) + return ret; spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags); iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf, @@ -2558,7 +2551,6 @@ static int irdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, struct uverbs_attr_bundle *attrs) { -#define IRDMA_CREATE_CQ_MIN_REQ_LEN offsetofend(struct irdma_create_cq_req, user_cq_buf) #define IRDMA_CREATE_CQ_MIN_RESP_LEN offsetofend(struct irdma_create_cq_resp, cq_size) struct ib_udata *udata = &attrs->driver_udata; struct ib_device *ibdev = ibcq->device; @@ -2582,8 +2574,7 @@ static int irdma_create_cq(struct ib_cq *ibcq, if (err_code) return err_code; - if (udata && (udata->inlen < IRDMA_CREATE_CQ_MIN_REQ_LEN || - udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)) + if (udata && udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN) return -EINVAL; err_code = irdma_alloc_rsrc(rf, rf->allocated_cqs, rf->max_cq, &cq_num, @@ -2625,11 +2616,14 @@ static int irdma_create_cq(struct ib_cq *ibcq, ucontext = rdma_udata_to_drv_context(udata, struct irdma_ucontext, ibucontext); - if (ib_copy_from_udata(&req, udata, - min(sizeof(req), udata->inlen))) { - err_code = -EFAULT; + /* Even though the last member of struct irdma_create_cq_req + * was always user_shadow_area, we need backwards compat with + * the legacy i40iw struct i40iw_ucreate_cq which stopped + * at user_cq_buffer. + */ + err_code = ib_copy_validate_udata_in(udata, req, user_cq_buf); + if (err_code) goto cq_free_rsrc; - } spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags); iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf, @@ -3613,7 +3607,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, struct ib_dmah *dmah, struct ib_udata *udata) { -#define IRDMA_MEM_REG_MIN_REQ_LEN offsetofend(struct irdma_mem_reg_req, sq_pages) struct irdma_device *iwdev = to_iwdev(pd->device); struct irdma_mem_reg_req req = {}; struct ib_umem *region = NULL; @@ -3623,6 +3616,10 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, if (dmah) return ERR_PTR(-EOPNOTSUPP); + err = ib_copy_validate_udata_in(udata, req, sq_pages); + if (err) + return ERR_PTR(err); + err = ib_respond_empty_udata(udata); if (err) return ERR_PTR(err); @@ -3630,9 +3627,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size) return ERR_PTR(-EINVAL); - if (udata->inlen < IRDMA_MEM_REG_MIN_REQ_LEN) - return ERR_PTR(-EINVAL); - region = ib_umem_get_va(pd->device, start, len, access); if (IS_ERR(region)) { @@ -3641,11 +3635,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, return (struct ib_mr *)region; } - if (ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen))) { - ib_umem_release(region); - return ERR_PTR(-EFAULT); - } - iwmr = irdma_alloc_iwmr(region, pd, virt, req.reg_type); if (IS_ERR(iwmr)) { ib_umem_release(region);