RDMA/verbs: Check existence of function prior to accessing it
authorLeon Romanovsky <leonro@mellanox.com>
Wed, 14 Feb 2018 12:38:43 +0000 (14:38 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Fri, 16 Feb 2018 16:18:55 +0000 (09:18 -0700)
Update all the flows to ensure that function pointer exists prior
to accessing it.

This is much safer than checking the uverbs_ex_mask variable, especially
since we know that test isn't working properly and will be removed
in -next.

This prevents a user triggereable oops.

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/uverbs_cmd.c

index c4560d84dfaebd550f504f2ed6b5f30bfb7ad520..c91f9a80b83134f1cf6e19215bc14afd5968da01 100644 (file)
@@ -309,6 +309,9 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
 {
        struct ib_qp *qp;
 
+       if (!dev->create_qp)
+               return ERR_PTR(-EOPNOTSUPP);
+
        qp = dev->create_qp(pd, attr, udata);
        if (IS_ERR(qp))
                return qp;
index cd9fbd7c82b01aac6d6939616c45302f77998016..dbcfb313cee9f7ef785cc3bed64d0c7a2b6b95dc 100644 (file)
@@ -978,6 +978,9 @@ static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file,
        struct ib_uverbs_ex_create_cq_resp resp;
        struct ib_cq_init_attr attr = {};
 
+       if (!ib_dev->create_cq)
+               return ERR_PTR(-EOPNOTSUPP);
+
        if (cmd->comp_vector >= file->device->num_comp_vectors)
                return ERR_PTR(-EINVAL);
 
@@ -2947,6 +2950,11 @@ int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file,
                wq_init_attr.create_flags = cmd.create_flags;
        obj->uevent.events_reported = 0;
        INIT_LIST_HEAD(&obj->uevent.event_list);
+
+       if (!pd->device->create_wq) {
+               err = -EOPNOTSUPP;
+               goto err_put_cq;
+       }
        wq = pd->device->create_wq(pd, &wq_init_attr, uhw);
        if (IS_ERR(wq)) {
                err = PTR_ERR(wq);
@@ -3090,7 +3098,12 @@ int ib_uverbs_ex_modify_wq(struct ib_uverbs_file *file,
                wq_attr.flags = cmd.flags;
                wq_attr.flags_mask = cmd.flags_mask;
        }
+       if (!wq->device->modify_wq) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
        ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw);
+out:
        uobj_put_obj_read(wq);
        return ret;
 }
@@ -3187,6 +3200,11 @@ int ib_uverbs_ex_create_rwq_ind_table(struct ib_uverbs_file *file,
 
        init_attr.log_ind_tbl_size = cmd.log_ind_tbl_size;
        init_attr.ind_tbl = wqs;
+
+       if (!ib_dev->create_rwq_ind_table) {
+               err = -EOPNOTSUPP;
+               goto err_uobj;
+       }
        rwq_ind_tbl = ib_dev->create_rwq_ind_table(ib_dev, &init_attr, uhw);
 
        if (IS_ERR(rwq_ind_tbl)) {
@@ -3776,6 +3794,9 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
        struct ib_device_attr attr = {0};
        int err;
 
+       if (!ib_dev->query_device)
+               return -EOPNOTSUPP;
+
        if (ucore->inlen < sizeof(cmd))
                return -EINVAL;