RDMA: Check attr_mask during modify_qp
Each driver should check that it can support the provided attr_mask during modify_qp. IB_USER_VERBS_EX_CMD_MODIFY_QP was being used to block modify_qp_ex because the driver didn't check RATE_LIMIT. Link: https://lore.kernel.org/r/6-v1-caa70ba3d1ab+1436e-ucmd_mask_jgg@nvidia.com Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
@@ -639,6 +639,7 @@ struct ib_device *_ib_alloc_device(size_t size)
|
|||||||
BIT_ULL(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL) |
|
BIT_ULL(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL) |
|
||||||
BIT_ULL(IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
|
BIT_ULL(IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
|
||||||
BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_CQ) |
|
BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_CQ) |
|
||||||
|
BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_QP) |
|
||||||
BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
|
BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
|
||||||
BIT_ULL(IB_USER_VERBS_EX_CMD_QUERY_DEVICE);
|
BIT_ULL(IB_USER_VERBS_EX_CMD_QUERY_DEVICE);
|
||||||
|
|
||||||
|
|||||||
@@ -1906,8 +1906,7 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (cmd.base.attr_mask &
|
if (cmd.base.attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1))
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
return modify_qp(attrs, &cmd);
|
return modify_qp(attrs, &cmd);
|
||||||
@@ -1929,10 +1928,7 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs)
|
|||||||
* Last bit is reserved for extending the attr_mask by
|
* Last bit is reserved for extending the attr_mask by
|
||||||
* using another field.
|
* using another field.
|
||||||
*/
|
*/
|
||||||
BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1ULL << 31));
|
if (cmd.base.attr_mask & ~(IB_QP_ATTR_STANDARD_BITS | IB_QP_RATE_LIMIT))
|
||||||
|
|
||||||
if (cmd.base.attr_mask &
|
|
||||||
~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1))
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
ret = modify_qp(attrs, &cmd);
|
ret = modify_qp(attrs, &cmd);
|
||||||
|
|||||||
@@ -1829,6 +1829,9 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
|||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
u8 nw_type;
|
u8 nw_type;
|
||||||
|
|
||||||
|
if (qp_attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
qp->qplib_qp.modify_flags = 0;
|
qp->qplib_qp.modify_flags = 0;
|
||||||
if (qp_attr_mask & IB_QP_STATE) {
|
if (qp_attr_mask & IB_QP_STATE) {
|
||||||
curr_qp_state = __to_ib_qp_state(qp->qplib_qp.cur_qp_state);
|
curr_qp_state = __to_ib_qp_state(qp->qplib_qp.cur_qp_state);
|
||||||
|
|||||||
@@ -2374,6 +2374,9 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
|
|
||||||
pr_debug("ib_qp %p\n", ibqp);
|
pr_debug("ib_qp %p\n", ibqp);
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* iwarp does not support the RTR state */
|
/* iwarp does not support the RTR state */
|
||||||
if ((attr_mask & IB_QP_STATE) && (attr->qp_state == IB_QPS_RTR))
|
if ((attr_mask & IB_QP_STATE) && (attr->qp_state == IB_QPS_RTR))
|
||||||
attr_mask &= ~IB_QP_STATE;
|
attr_mask &= ~IB_QP_STATE;
|
||||||
|
|||||||
@@ -917,6 +917,9 @@ int efa_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
|||||||
enum ib_qp_state new_state;
|
enum ib_qp_state new_state;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (qp_attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (udata->inlen &&
|
if (udata->inlen &&
|
||||||
!ib_is_udata_cleared(udata, 0, udata->inlen)) {
|
!ib_is_udata_cleared(udata, 0, udata->inlen)) {
|
||||||
ibdev_dbg(&dev->ibdev,
|
ibdev_dbg(&dev->ibdev,
|
||||||
|
|||||||
@@ -3256,6 +3256,8 @@ static int hns_roce_v1_modify_qp(struct ib_qp *ibqp,
|
|||||||
enum ib_qp_state cur_state,
|
enum ib_qp_state cur_state,
|
||||||
enum ib_qp_state new_state)
|
enum ib_qp_state new_state)
|
||||||
{
|
{
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
|
if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
|
||||||
return hns_roce_v1_m_sqp(ibqp, attr, attr_mask, cur_state,
|
return hns_roce_v1_m_sqp(ibqp, attr, attr_mask, cur_state,
|
||||||
|
|||||||
@@ -4757,6 +4757,9 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
|
|||||||
unsigned long rq_flag = 0;
|
unsigned long rq_flag = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In v2 engine, software pass context and context mask to hardware
|
* In v2 engine, software pass context and context mask to hardware
|
||||||
* when modifying qp. If software need modify some fields in context,
|
* when modifying qp. If software need modify some fields in context,
|
||||||
|
|||||||
@@ -855,6 +855,9 @@ int i40iw_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
u32 err;
|
u32 err;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
ctx_info = &iwqp->ctx_info;
|
ctx_info = &iwqp->ctx_info;
|
||||||
iwarp_info = &iwqp->iwarp_info;
|
iwarp_info = &iwqp->iwarp_info;
|
||||||
|
|||||||
@@ -2787,6 +2787,9 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
struct mlx4_ib_qp *mqp = to_mqp(ibqp);
|
struct mlx4_ib_qp *mqp = to_mqp(ibqp);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
ret = _mlx4_ib_modify_qp(ibqp, attr, attr_mask, udata);
|
ret = _mlx4_ib_modify_qp(ibqp, attr, attr_mask, udata);
|
||||||
|
|
||||||
if (mqp->mlx4_ib_qp_type == MLX4_IB_QPT_GSI) {
|
if (mqp->mlx4_ib_qp_type == MLX4_IB_QPT_GSI) {
|
||||||
|
|||||||
@@ -4144,8 +4144,7 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
|
|||||||
(1ull << IB_USER_VERBS_CMD_DESTROY_AH);
|
(1ull << IB_USER_VERBS_CMD_DESTROY_AH);
|
||||||
dev->ib_dev.uverbs_ex_cmd_mask |=
|
dev->ib_dev.uverbs_ex_cmd_mask |=
|
||||||
(1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ) |
|
(1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ) |
|
||||||
(1ull << IB_USER_VERBS_EX_CMD_CREATE_QP) |
|
(1ull << IB_USER_VERBS_EX_CMD_CREATE_QP);
|
||||||
(1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP);
|
|
||||||
|
|
||||||
if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&
|
if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&
|
||||||
IS_ENABLED(CONFIG_MLX5_CORE_IPOIB))
|
IS_ENABLED(CONFIG_MLX5_CORE_IPOIB))
|
||||||
|
|||||||
@@ -4247,6 +4247,9 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
int err = -EINVAL;
|
int err = -EINVAL;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
|
if (attr_mask & ~(IB_QP_ATTR_STANDARD_BITS | IB_QP_RATE_LIMIT))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (ibqp->rwq_ind_tbl)
|
if (ibqp->rwq_ind_tbl)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
|
|||||||
@@ -863,6 +863,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
|
|||||||
enum ib_qp_state cur_state, new_state;
|
enum ib_qp_state cur_state, new_state;
|
||||||
int err = -EINVAL;
|
int err = -EINVAL;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
mutex_lock(&qp->mutex);
|
mutex_lock(&qp->mutex);
|
||||||
if (attr_mask & IB_QP_CUR_STATE) {
|
if (attr_mask & IB_QP_CUR_STATE) {
|
||||||
cur_state = attr->cur_qp_state;
|
cur_state = attr->cur_qp_state;
|
||||||
|
|||||||
@@ -1391,6 +1391,9 @@ int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
struct ocrdma_dev *dev;
|
struct ocrdma_dev *dev;
|
||||||
enum ib_qp_state old_qps, new_qps;
|
enum ib_qp_state old_qps, new_qps;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
qp = get_ocrdma_qp(ibqp);
|
qp = get_ocrdma_qp(ibqp);
|
||||||
dev = get_ocrdma_dev(ibqp->device);
|
dev = get_ocrdma_dev(ibqp->device);
|
||||||
|
|
||||||
|
|||||||
@@ -2472,6 +2472,9 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
"modify qp: qp %p attr_mask=0x%x, state=%d", qp, attr_mask,
|
"modify qp: qp %p attr_mask=0x%x, state=%d", qp, attr_mask,
|
||||||
attr->qp_state);
|
attr->qp_state);
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
old_qp_state = qedr_get_ibqp_state(qp->state);
|
old_qp_state = qedr_get_ibqp_state(qp->state);
|
||||||
if (attr_mask & IB_QP_STATE)
|
if (attr_mask & IB_QP_STATE)
|
||||||
new_qp_state = attr->qp_state;
|
new_qp_state = attr->qp_state;
|
||||||
|
|||||||
@@ -557,6 +557,9 @@ int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
int status;
|
int status;
|
||||||
usnic_dbg("\n");
|
usnic_dbg("\n");
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
qp_grp = to_uqp_grp(ibqp);
|
qp_grp = to_uqp_grp(ibqp);
|
||||||
|
|
||||||
mutex_lock(&qp_grp->vf->pf->usdev_lock);
|
mutex_lock(&qp_grp->vf->pf->usdev_lock);
|
||||||
|
|||||||
@@ -544,6 +544,9 @@ int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
enum ib_qp_state cur_state, next_state;
|
enum ib_qp_state cur_state, next_state;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* Sanity checking. Should need lock here */
|
/* Sanity checking. Should need lock here */
|
||||||
mutex_lock(&qp->mutex);
|
mutex_lock(&qp->mutex);
|
||||||
cur_state = (attr_mask & IB_QP_CUR_STATE) ? attr->cur_qp_state :
|
cur_state = (attr_mask & IB_QP_CUR_STATE) ? attr->cur_qp_state :
|
||||||
|
|||||||
@@ -1469,6 +1469,9 @@ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
int pmtu = 0; /* for gcc warning only */
|
int pmtu = 0; /* for gcc warning only */
|
||||||
int opa_ah;
|
int opa_ah;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
spin_lock_irq(&qp->r_lock);
|
spin_lock_irq(&qp->r_lock);
|
||||||
spin_lock(&qp->s_hlock);
|
spin_lock(&qp->s_hlock);
|
||||||
spin_lock(&qp->s_lock);
|
spin_lock(&qp->s_lock);
|
||||||
|
|||||||
@@ -436,6 +436,9 @@ static int rxe_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||||||
struct rxe_dev *rxe = to_rdev(ibqp->device);
|
struct rxe_dev *rxe = to_rdev(ibqp->device);
|
||||||
struct rxe_qp *qp = to_rqp(ibqp);
|
struct rxe_qp *qp = to_rqp(ibqp);
|
||||||
|
|
||||||
|
if (mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
err = rxe_qp_chk_attr(rxe, qp, attr, mask);
|
err = rxe_qp_chk_attr(rxe, qp, attr, mask);
|
||||||
if (err)
|
if (err)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|||||||
@@ -544,6 +544,9 @@ int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr,
|
|||||||
if (!attr_mask)
|
if (!attr_mask)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
memset(&new_attrs, 0, sizeof(new_attrs));
|
memset(&new_attrs, 0, sizeof(new_attrs));
|
||||||
|
|
||||||
if (attr_mask & IB_QP_ACCESS_FLAGS) {
|
if (attr_mask & IB_QP_ACCESS_FLAGS) {
|
||||||
|
|||||||
@@ -1234,6 +1234,8 @@ enum ib_qp_attr_mask {
|
|||||||
IB_QP_RESERVED3 = (1<<23),
|
IB_QP_RESERVED3 = (1<<23),
|
||||||
IB_QP_RESERVED4 = (1<<24),
|
IB_QP_RESERVED4 = (1<<24),
|
||||||
IB_QP_RATE_LIMIT = (1<<25),
|
IB_QP_RATE_LIMIT = (1<<25),
|
||||||
|
|
||||||
|
IB_QP_ATTR_STANDARD_BITS = GENMASK(20, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ib_qp_state {
|
enum ib_qp_state {
|
||||||
|
|||||||
@@ -596,20 +596,6 @@ enum {
|
|||||||
IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE,
|
IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
/*
|
|
||||||
* This value is equal to IB_QP_DEST_QPN.
|
|
||||||
*/
|
|
||||||
IB_USER_LEGACY_LAST_QP_ATTR_MASK = 1ULL << 20,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
/*
|
|
||||||
* This value is equal to IB_QP_RATE_LIMIT.
|
|
||||||
*/
|
|
||||||
IB_USER_LAST_QP_ATTR_MASK = 1ULL << 25,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ib_uverbs_ex_create_qp {
|
struct ib_uverbs_ex_create_qp {
|
||||||
__aligned_u64 user_handle;
|
__aligned_u64 user_handle;
|
||||||
__u32 pd_handle;
|
__u32 pd_handle;
|
||||||
|
|||||||
Reference in New Issue
Block a user