IB/core: Fix input len in multiple user verbs
authorAmrani, Ram <Ram.Amrani@cavium.com>
Tue, 27 Jun 2017 14:04:42 +0000 (17:04 +0300)
committerDoug Ledford <dledford@redhat.com>
Tue, 22 Aug 2017 18:02:29 +0000 (14:02 -0400)
Most user verbs pass user data to the kernel with the inclusion of the
ib_uverbs_cmd_hdr structure. This is problematic because the vendor has
no ideas if the verb was called by a legacy verb or an extended verb.
Also, the incosistency between the verbs is confusing.

Fixes: 565197dd8fb1 ("IB/core: Extend ib_uverbs_create_cq")
Signed-off-by: Ram Amrani <Ram.Amrani@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/hw/mlx5/cq.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mthca/mthca_provider.c

index a21881e..7ea5a3b 100644 (file)
@@ -91,9 +91,10 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
                goto err;
        }
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        ret = ib_rdmacg_try_charge(&cg_obj, ib_dev, RDMACG_RESOURCE_HCA_HANDLE);
        if (ret)
@@ -319,9 +320,10 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                   in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                   out_len - sizeof(resp));
 
        uobj  = uobj_alloc(uobj_get_type(pd), file->ucontext);
        if (IS_ERR(uobj))
@@ -488,9 +490,10 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof  resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                   in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                   out_len - sizeof(resp));
 
        mutex_lock(&file->device->xrcd_tree_mutex);
 
@@ -652,9 +655,10 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                   in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                   out_len - sizeof(resp));
 
        if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
                return -EINVAL;
@@ -746,7 +750,8 @@ ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
 
        INIT_UDATA(&udata, buf + sizeof(cmd),
                   (unsigned long) cmd.response + sizeof(resp),
-                  in_len - sizeof(cmd), out_len - sizeof(resp));
+                   in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                   out_len - sizeof(resp));
 
        if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
                return -EINVAL;
@@ -1086,7 +1091,8 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
 
        INIT_UDATA(&uhw, buf + sizeof(cmd),
                   (unsigned long)cmd.response + sizeof(resp),
-                  in_len - sizeof(cmd), out_len - sizeof(resp));
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        memset(&cmd_ex, 0, sizeof(cmd_ex));
        cmd_ex.user_handle = cmd.user_handle;
@@ -1167,9 +1173,10 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        cq = uobj_get_obj_read(cq, cmd.cq_handle, file->ucontext);
        if (!cq)
@@ -1742,9 +1749,10 @@ ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        obj  = (struct ib_uqp_object *)uobj_alloc(uobj_get_type(qp),
                                                  file->ucontext);
@@ -2055,7 +2063,8 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
                return -EOPNOTSUPP;
 
        INIT_UDATA(&udata, buf + sizeof(cmd.base), NULL,
-                  in_len - sizeof(cmd.base), out_len);
+                  in_len - sizeof(cmd.base) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len);
 
        ret = modify_qp(file, &cmd, &udata);
        if (ret)
@@ -2561,7 +2570,8 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
 
        INIT_UDATA(&udata, buf + sizeof(cmd),
                   (unsigned long)cmd.response + sizeof(resp),
-                  in_len - sizeof(cmd), out_len - sizeof(resp));
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        uobj  = uobj_alloc(uobj_get_type(ah), file->ucontext);
        if (IS_ERR(uobj))
@@ -3625,10 +3635,10 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        xcmd.max_sge     = cmd.max_sge;
        xcmd.srq_limit   = cmd.srq_limit;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
-                  out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        ret = __uverbs_create_xsrq(file, ib_dev, &xcmd, &udata);
        if (ret)
@@ -3652,10 +3662,10 @@ ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       INIT_UDATA(&udata, buf + sizeof cmd,
-                  (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
-                  out_len - sizeof resp);
+       INIT_UDATA(&udata, buf + sizeof(cmd),
+                  (unsigned long) cmd.response + sizeof(resp),
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof(resp));
 
        ret = __uverbs_create_xsrq(file, ib_dev, &cmd, &udata);
        if (ret)
index a384d72..c155df4 100644 (file)
@@ -751,10 +751,8 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata,
        void *cqc;
        int err;
 
-       ucmdlen =
-               (udata->inlen - sizeof(struct ib_uverbs_cmd_hdr) <
-                sizeof(ucmd)) ? (sizeof(ucmd) -
-                                 sizeof(ucmd.reserved)) : sizeof(ucmd);
+       ucmdlen = udata->inlen < sizeof(ucmd) ?
+                 (sizeof(ucmd) - sizeof(ucmd.reserved)) : sizeof(ucmd);
 
        if (ib_copy_from_udata(&ucmd, udata, ucmdlen))
                return -EFAULT;
index cde7d1c..e2fffdc 100644 (file)
@@ -1273,7 +1273,6 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        struct mlx5_bfreg_info *bfregi;
        int ver;
        int err;
-       size_t reqlen;
        size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2,
                                     max_cqe_version);
        bool lib_uar_4k;
@@ -1281,18 +1280,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        if (!dev->ib_active)
                return ERR_PTR(-EAGAIN);
 
-       if (udata->inlen < sizeof(struct ib_uverbs_cmd_hdr))
-               return ERR_PTR(-EINVAL);
-
-       reqlen = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr);
-       if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req))
+       if (udata->inlen == sizeof(struct mlx5_ib_alloc_ucontext_req))
                ver = 0;
-       else if (reqlen >= min_req_v2)
+       else if (udata->inlen >= min_req_v2)
                ver = 2;
        else
                return ERR_PTR(-EINVAL);
 
-       err = ib_copy_from_udata(&req, udata, min(reqlen, sizeof(req)));
+       err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));
        if (err)
                return ERR_PTR(err);
 
index eae9bff..6fee779 100644 (file)
@@ -914,7 +914,7 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        int err = 0;
        int write_mtt_size;
 
-       if (udata->inlen - sizeof (struct ib_uverbs_cmd_hdr) < sizeof ucmd) {
+       if (udata->inlen < sizeof ucmd) {
                if (!to_mucontext(pd->uobject->context)->reg_mr_warned) {
                        mthca_warn(dev, "Process '%s' did not pass in MR attrs.\n",
                                   current->comm);