aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorLeon Romanovsky <leonro@mellanox.com>2020-04-27 18:46:32 +0300
committerJason Gunthorpe <jgg@mellanox.com>2020-04-30 18:45:45 -0300
commit6f2cf76e6ec7885de116cfc9c08057f2f7873629 (patch)
tree077f4b111be9c2b87ba23b9997a5ed2763907a6d /drivers/infiniband
parent5d6fffed1cfd0c368a9089acb9fcc902c649c31c (diff)
downloadlinux-6f2cf76e6ec7885de116cfc9c08057f2f7873629.tar.gz
RDMA/mlx5: Handle udate outlen checks in one place
Place in one function all udata size checks. This will allow us move ib_copy_to_udata() in general place and ensure that it will be performed after call to the FW. Link: https://lore.kernel.org/r/20200427154636.381474-33-leon@kernel.org Reviewed-by: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 8daa8bc6b9c7..0d06706e6ce1 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1613,6 +1613,7 @@ static void destroy_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *q
struct mlx5_create_qp_params {
struct ib_udata *udata;
size_t inlen;
+ size_t outlen;
void *ucmd;
u8 is_rss_raw : 1;
struct ib_qp_init_attr *attr;
@@ -1638,15 +1639,9 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct ib_pd *pd,
void *hfso;
u32 selected_fields = 0;
u32 outer_l4;
- size_t min_resp_len;
u32 tdn = mucontext->tdn;
u8 lb_flag = 0;
- min_resp_len =
- offsetof(typeof(resp), bfreg_index) + sizeof(resp.bfreg_index);
- if (udata->outlen < min_resp_len)
- return -EINVAL;
-
if (ucmd->comp_mask) {
mlx5_ib_dbg(dev, "invalid comp mask\n");
return -EOPNOTSUPP;
@@ -2780,26 +2775,43 @@ static int process_create_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
return (create_flags) ? -EINVAL : 0;
}
-static size_t process_udata_size(struct ib_qp_init_attr *attr,
- struct ib_udata *udata)
+static int process_udata_size(struct mlx5_ib_dev *dev,
+ struct mlx5_create_qp_params *params)
{
size_t ucmd = sizeof(struct mlx5_ib_create_qp);
+ struct ib_qp_init_attr *attr = params->attr;
+ struct ib_udata *udata = params->udata;
+ size_t outlen = udata->outlen;
size_t inlen = udata->inlen;
- if (attr->qp_type == IB_QPT_DRIVER)
- return (inlen < ucmd) ? 0 : ucmd;
+ params->outlen = min(outlen, sizeof(struct mlx5_ib_create_qp_resp));
+ if (attr->qp_type == IB_QPT_DRIVER) {
+ params->inlen = (inlen < ucmd) ? 0 : ucmd;
+ goto out;
+ }
- if (!attr->rwq_ind_tbl)
- return ucmd;
+ if (!params->is_rss_raw) {
+ params->inlen = ucmd;
+ goto out;
+ }
+ /* RSS RAW QP */
if (inlen < offsetofend(struct mlx5_ib_create_qp_rss, flags))
- return 0;
+ return -EINVAL;
+
+ if (outlen < offsetofend(struct mlx5_ib_create_qp_resp, bfreg_index))
+ return -EINVAL;
ucmd = sizeof(struct mlx5_ib_create_qp_rss);
if (inlen > ucmd && !ib_is_udata_cleared(udata, ucmd, inlen - ucmd))
- return 0;
+ return -EINVAL;
+
+ params->inlen = min(ucmd, inlen);
+out:
+ if (!params->inlen)
+ mlx5_ib_dbg(dev, "udata is too small or not cleared\n");
- return min(ucmd, inlen);
+ return (params->inlen) ? 0 : -EINVAL;
}
static int create_raw_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
@@ -2883,9 +2895,9 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
params.is_rss_raw = !!attr->rwq_ind_tbl;
if (udata) {
- params.inlen = process_udata_size(attr, udata);
- if (!params.inlen)
- return ERR_PTR(-EINVAL);
+ err = process_udata_size(dev, &params);
+ if (err)
+ return ERR_PTR(err);
params.ucmd = kzalloc(params.inlen, GFP_KERNEL);
if (!params.ucmd)