From a140692a52d2e12ba6a76dd042d556348e8bb55a Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Mon, 12 Nov 2018 22:59:58 +0200 Subject: [PATCH] RDMA/uverbs: Check for NULL driver methods for every write call Add annotations to the uverbs_api structure indicating which driver methods are called by the implementation. If the required method is NULL the write API will be not be callable. This effectively duplicates the cmd_mask system, however it does it by expressing invariants required by the core code, not by delegating decision making to the driver. This is another step toward eliminating cmd_mask. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/uverbs_cmd.c | 208 +++++++++++++++----------- drivers/infiniband/core/uverbs_uapi.c | 47 +++++- include/rdma/uverbs_ioctl.h | 16 ++ 3 files changed, 174 insertions(+), 97 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 7c7ec1575511..e2fcaf398a4d 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -991,11 +991,6 @@ static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file, if (IS_ERR(obj)) return obj; - if (!ib_dev->create_cq) { - ret = -EOPNOTSUPP; - goto err; - } - if (cmd->comp_channel >= 0) { ev_file = ib_uverbs_lookup_comp_file(cmd->comp_channel, file); if (IS_ERR(ev_file)) { @@ -2541,8 +2536,7 @@ static ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, goto out; resp.bad_wr = 0; - ret = srq->device->post_srq_recv ? - srq->device->post_srq_recv(srq, wr, &bad_wr) : -EOPNOTSUPP; + ret = srq->device->post_srq_recv(srq, wr, &bad_wr); uobj_put_obj_read(srq); @@ -3144,10 +3138,6 @@ static int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file, 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); @@ -3277,12 +3267,7 @@ static 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; } @@ -3380,10 +3365,6 @@ static 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)) { @@ -3548,11 +3529,6 @@ static int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, goto err_put; } - if (!qp->device->create_flow) { - err = -EOPNOTSUPP; - goto err_put; - } - flow_attr = kzalloc(struct_size(flow_attr, flows, cmd.flow_attr.num_of_specs), GFP_KERNEL); if (!flow_attr) { @@ -3971,9 +3947,6 @@ static int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, return PTR_ERR(ucontext); ib_dev = ucontext->device; - if (!ib_dev->query_device) - return -EOPNOTSUPP; - if (ucore->inlen < sizeof(cmd)) return -EINVAL; @@ -4123,11 +4096,14 @@ static int ib_uverbs_ex_modify_cq(struct ib_uverbs_file *file, } const struct uapi_definition uverbs_def_write_intf[] = { - DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_AH, - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_AH, - ib_uverbs_create_ah), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_AH, - ib_uverbs_destroy_ah)), + DECLARE_UVERBS_OBJECT( + UVERBS_OBJECT_AH, + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_AH, + ib_uverbs_create_ah, + UAPI_DEF_METHOD_NEEDS_FN(create_ah)), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_AH, + ib_uverbs_destroy_ah, + UAPI_DEF_METHOD_NEEDS_FN(destroy_ah))), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_COMP_CHANNEL, @@ -4137,19 +4113,26 @@ const struct uapi_definition uverbs_def_write_intf[] = { DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_CQ, DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_CQ, - ib_uverbs_create_cq), + ib_uverbs_create_cq, + UAPI_DEF_METHOD_NEEDS_FN(create_cq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_CQ, - ib_uverbs_destroy_cq), + ib_uverbs_destroy_cq, + UAPI_DEF_METHOD_NEEDS_FN(destroy_cq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POLL_CQ, - ib_uverbs_poll_cq), + ib_uverbs_poll_cq, + UAPI_DEF_METHOD_NEEDS_FN(poll_cq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REQ_NOTIFY_CQ, - ib_uverbs_req_notify_cq), + ib_uverbs_req_notify_cq, + UAPI_DEF_METHOD_NEEDS_FN(req_notify_cq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_RESIZE_CQ, - ib_uverbs_resize_cq), + ib_uverbs_resize_cq, + UAPI_DEF_METHOD_NEEDS_FN(resize_cq)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_CQ, - ib_uverbs_ex_create_cq), + ib_uverbs_ex_create_cq, + UAPI_DEF_METHOD_NEEDS_FN(create_cq)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_CQ, - ib_uverbs_ex_modify_cq)), + ib_uverbs_ex_modify_cq, + UAPI_DEF_METHOD_NEEDS_FN(create_cq))), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_DEVICE, @@ -4158,98 +4141,141 @@ const struct uapi_definition uverbs_def_write_intf[] = { DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_DEVICE, ib_uverbs_query_device), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_PORT, - ib_uverbs_query_port), + ib_uverbs_query_port, + UAPI_DEF_METHOD_NEEDS_FN(query_port)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_QUERY_DEVICE, - ib_uverbs_ex_query_device)), + ib_uverbs_ex_query_device, + UAPI_DEF_METHOD_NEEDS_FN(query_device)), + UAPI_DEF_OBJ_NEEDS_FN(alloc_ucontext), + UAPI_DEF_OBJ_NEEDS_FN(dealloc_ucontext)), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_FLOW, DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_FLOW, - ib_uverbs_ex_create_flow), + ib_uverbs_ex_create_flow, + UAPI_DEF_METHOD_NEEDS_FN(create_flow)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_FLOW, - ib_uverbs_ex_destroy_flow)), + ib_uverbs_ex_destroy_flow, + UAPI_DEF_METHOD_NEEDS_FN(destroy_flow))), - DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MR, - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEREG_MR, - ib_uverbs_dereg_mr), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REG_MR, - ib_uverbs_reg_mr), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REREG_MR, - ib_uverbs_rereg_mr)), + DECLARE_UVERBS_OBJECT( + UVERBS_OBJECT_MR, + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEREG_MR, + ib_uverbs_dereg_mr, + UAPI_DEF_METHOD_NEEDS_FN(dereg_mr)), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REG_MR, + ib_uverbs_reg_mr, + UAPI_DEF_METHOD_NEEDS_FN(reg_user_mr)), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REREG_MR, + ib_uverbs_rereg_mr, + UAPI_DEF_METHOD_NEEDS_FN(rereg_user_mr))), - DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MW, - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_MW, - ib_uverbs_alloc_mw), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_MW, - ib_uverbs_dealloc_mw)), + DECLARE_UVERBS_OBJECT( + UVERBS_OBJECT_MW, + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_MW, + ib_uverbs_alloc_mw, + UAPI_DEF_METHOD_NEEDS_FN(alloc_mw)), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_MW, + ib_uverbs_dealloc_mw, + UAPI_DEF_METHOD_NEEDS_FN(dealloc_mw))), - DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_PD, - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_PD, - ib_uverbs_alloc_pd), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_PD, - ib_uverbs_dealloc_pd)), + DECLARE_UVERBS_OBJECT( + UVERBS_OBJECT_PD, + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_PD, + ib_uverbs_alloc_pd, + UAPI_DEF_METHOD_NEEDS_FN(alloc_pd)), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_PD, + ib_uverbs_dealloc_pd, + UAPI_DEF_METHOD_NEEDS_FN(dealloc_pd))), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_QP, DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ATTACH_MCAST, - ib_uverbs_attach_mcast), + ib_uverbs_attach_mcast, + UAPI_DEF_METHOD_NEEDS_FN(attach_mcast), + UAPI_DEF_METHOD_NEEDS_FN(detach_mcast)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_QP, - ib_uverbs_create_qp), + ib_uverbs_create_qp, + UAPI_DEF_METHOD_NEEDS_FN(create_qp)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_QP, - ib_uverbs_destroy_qp), + ib_uverbs_destroy_qp, + UAPI_DEF_METHOD_NEEDS_FN(destroy_qp)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DETACH_MCAST, - ib_uverbs_detach_mcast), + ib_uverbs_detach_mcast, + UAPI_DEF_METHOD_NEEDS_FN(detach_mcast)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_QP, - ib_uverbs_modify_qp), + ib_uverbs_modify_qp, + UAPI_DEF_METHOD_NEEDS_FN(modify_qp)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_RECV, - ib_uverbs_post_recv), + ib_uverbs_post_recv, + UAPI_DEF_METHOD_NEEDS_FN(post_recv)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SEND, - ib_uverbs_post_send), + ib_uverbs_post_send, + UAPI_DEF_METHOD_NEEDS_FN(post_send)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_QP, - ib_uverbs_query_qp), + ib_uverbs_query_qp, + UAPI_DEF_METHOD_NEEDS_FN(query_qp)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_QP, - ib_uverbs_ex_create_qp), + ib_uverbs_ex_create_qp, + UAPI_DEF_METHOD_NEEDS_FN(create_qp)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_QP, - ib_uverbs_ex_modify_qp)), + ib_uverbs_ex_modify_qp, + UAPI_DEF_METHOD_NEEDS_FN(modify_qp))), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_RWQ_IND_TBL, - DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL, - ib_uverbs_ex_create_rwq_ind_table), - DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL, - ib_uverbs_ex_destroy_rwq_ind_table)), + DECLARE_UVERBS_WRITE_EX( + IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL, + ib_uverbs_ex_create_rwq_ind_table, + UAPI_DEF_METHOD_NEEDS_FN(create_rwq_ind_table)), + DECLARE_UVERBS_WRITE_EX( + IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL, + ib_uverbs_ex_destroy_rwq_ind_table, + UAPI_DEF_METHOD_NEEDS_FN(destroy_rwq_ind_table))), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_WQ, DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_WQ, - ib_uverbs_ex_create_wq), + ib_uverbs_ex_create_wq, + UAPI_DEF_METHOD_NEEDS_FN(create_wq)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_WQ, - ib_uverbs_ex_destroy_wq), + ib_uverbs_ex_destroy_wq, + UAPI_DEF_METHOD_NEEDS_FN(destroy_wq)), DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_WQ, - ib_uverbs_ex_modify_wq)), + ib_uverbs_ex_modify_wq, + UAPI_DEF_METHOD_NEEDS_FN(modify_wq))), DECLARE_UVERBS_OBJECT( UVERBS_OBJECT_SRQ, DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_SRQ, - ib_uverbs_create_srq), + ib_uverbs_create_srq, + UAPI_DEF_METHOD_NEEDS_FN(create_srq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_XSRQ, - ib_uverbs_create_xsrq), + ib_uverbs_create_xsrq, + UAPI_DEF_METHOD_NEEDS_FN(create_srq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_SRQ, - ib_uverbs_destroy_srq), + ib_uverbs_destroy_srq, + UAPI_DEF_METHOD_NEEDS_FN(destroy_srq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_SRQ, - ib_uverbs_modify_srq), + ib_uverbs_modify_srq, + UAPI_DEF_METHOD_NEEDS_FN(modify_srq)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SRQ_RECV, - ib_uverbs_post_srq_recv), + ib_uverbs_post_srq_recv, + UAPI_DEF_METHOD_NEEDS_FN(post_srq_recv)), DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_SRQ, - ib_uverbs_query_srq)), + ib_uverbs_query_srq, + UAPI_DEF_METHOD_NEEDS_FN(query_srq))), - DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_XRCD, - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CLOSE_XRCD, - ib_uverbs_close_xrcd), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP, - ib_uverbs_open_qp), - DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_XRCD, - ib_uverbs_open_xrcd)), + DECLARE_UVERBS_OBJECT( + UVERBS_OBJECT_XRCD, + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CLOSE_XRCD, + ib_uverbs_close_xrcd, + UAPI_DEF_METHOD_NEEDS_FN(dealloc_xrcd)), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP, + ib_uverbs_open_qp), + DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_XRCD, + ib_uverbs_open_xrcd, + UAPI_DEF_METHOD_NEEDS_FN(alloc_xrcd))), {}, }; diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c index 1e880f1d9d62..a92adbe2b034 100644 --- a/drivers/infiniband/core/uverbs_uapi.c +++ b/drivers/infiniband/core/uverbs_uapi.c @@ -60,8 +60,11 @@ static void *uapi_add_get_elm(struct uverbs_api *uapi, u32 key, return elm; } -static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev, - const struct uapi_definition *def, u32 obj_key) +static int uapi_create_write(struct uverbs_api *uapi, + struct ib_device *ibdev, + const struct uapi_definition *def, + u32 obj_key, + u32 *cur_method_key) { struct uverbs_api_write_method *method_elm; u32 method_key = obj_key; @@ -93,6 +96,8 @@ static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev, method_elm->disabled = !(ibdev->uverbs_cmd_mask & BIT_ULL(def->write.command_num)); } + + *cur_method_key = method_key; return 0; } @@ -218,7 +223,8 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi, static int uapi_disable_elm(struct uverbs_api *uapi, const struct uapi_definition *def, - u32 obj_key) + u32 obj_key, + u32 method_key) { bool exists; @@ -233,6 +239,31 @@ static int uapi_disable_elm(struct uverbs_api *uapi, return 0; } + if (def->scope == UAPI_SCOPE_METHOD && + uapi_key_is_ioctl_method(method_key)) { + struct uverbs_api_ioctl_method *method_elm; + + method_elm = uapi_add_get_elm(uapi, method_key, + sizeof(*method_elm), &exists); + if (IS_ERR(method_elm)) + return PTR_ERR(method_elm); + method_elm->disabled = 1; + return 0; + } + + if (def->scope == UAPI_SCOPE_METHOD && + (uapi_key_is_write_method(method_key) || + uapi_key_is_write_ex_method(method_key))) { + struct uverbs_api_write_method *write_elm; + + write_elm = uapi_add_get_elm(uapi, method_key, + sizeof(*write_elm), &exists); + if (IS_ERR(write_elm)) + return PTR_ERR(write_elm); + write_elm->disabled = 1; + return 0; + } + WARN_ON(true); return -EINVAL; } @@ -243,6 +274,7 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, { const struct uapi_definition *def = def_list; u32 cur_obj_key = UVERBS_API_KEY_ERR; + u32 cur_method_key = UVERBS_API_KEY_ERR; bool exists; int rc; @@ -277,7 +309,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, if (*ibdev_fn) continue; - rc = uapi_disable_elm(uapi, def, cur_obj_key); + rc = uapi_disable_elm( + uapi, def, cur_obj_key, cur_method_key); if (rc) return rc; continue; @@ -286,7 +319,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, case UAPI_DEF_IS_SUPPORTED_FUNC: if (def->func_is_supported(ibdev)) continue; - rc = uapi_disable_elm(uapi, def, cur_obj_key); + rc = uapi_disable_elm( + uapi, def, cur_obj_key, cur_method_key); if (rc) return rc; continue; @@ -303,7 +337,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, } case UAPI_DEF_WRITE: - rc = uapi_create_write(uapi, ibdev, def, cur_obj_key); + rc = uapi_create_write( + uapi, ibdev, def, cur_obj_key, &cur_method_key); if (rc) return rc; continue; diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 5df8ed79ba6c..963dd6b70cde 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h @@ -350,6 +350,7 @@ enum uapi_definition_kind { enum uapi_definition_scope { UAPI_SCOPE_OBJECT = 1, + UAPI_SCOPE_METHOD = 2, }; struct uapi_definition { @@ -422,6 +423,21 @@ struct uapi_definition { sizeof(void *)), \ } +/* + * Method is only supported if the function pointer named ibdev_fn in struct + * ib_device is not NULL. + */ +#define UAPI_DEF_METHOD_NEEDS_FN(ibdev_fn) \ + { \ + .kind = UAPI_DEF_IS_SUPPORTED_DEV_FN, \ + .scope = UAPI_SCOPE_METHOD, \ + .needs_fn_offset = \ + offsetof(struct ib_device, ibdev_fn) + \ + BUILD_BUG_ON_ZERO( \ + sizeof(((struct ib_device *)0)->ibdev_fn) != \ + sizeof(void *)), \ + } + /* Call a function to determine if the entire object is supported or not */ #define UAPI_DEF_IS_OBJ_SUPPORTED(_func) \ { \