From bbb28ad9035f8efa9c5581b3809ff8055cc1f4b2 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:34 +0200 Subject: [PATCH 01/12] RDMA/uverbs: Remove out_len checks that are now done by the core write() methods must work with fixed sized structures as that is the only way to know where the udata segment starts. The common udata code now rejects any write() that has a response buffer shorter than the core's response. Thus all the checks of out_len for write methods are redundant and can be removed. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 50 ---------------------------- 1 file changed, 50 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index dc06b6914b5e..5708abc0e4d4 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -78,9 +78,6 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs, struct ib_device *ib_dev; int ret; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -231,9 +228,6 @@ static int ib_uverbs_query_device(struct uverbs_attr_bundle *attrs, if (IS_ERR(ucontext)) return PTR_ERR(ucontext); - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -282,9 +276,6 @@ static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs, return PTR_ERR(ucontext); ib_dev = ucontext->device; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -341,9 +332,6 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -493,9 +481,6 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs, int new_xrcd = 0; struct ib_device *ib_dev; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -642,9 +627,6 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -727,9 +709,6 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs, int ret; struct ib_uobject *uobj; - if (out_len < sizeof(resp)) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; @@ -822,9 +801,6 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (out_len < sizeof(resp)) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; @@ -893,9 +869,6 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, struct ib_uverbs_completion_event_file *ev_file; struct ib_device *ib_dev; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -1031,9 +1004,6 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, struct ib_udata ucore; struct ib_ucq_object *obj; - if (out_len < sizeof(resp)) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; @@ -1549,9 +1519,6 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp); int err; - if (out_len < resp_size) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; @@ -1641,9 +1608,6 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -2476,9 +2440,6 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -3667,10 +3628,6 @@ static int ib_uverbs_create_srq(struct uverbs_attr_bundle *attrs, { struct ib_uverbs_create_srq cmd; struct ib_uverbs_create_xsrq xcmd; - struct ib_uverbs_create_srq_resp resp; - - if (out_len < sizeof resp) - return -ENOSPC; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -3692,10 +3649,6 @@ static int ib_uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, int out_len) { struct ib_uverbs_create_xsrq cmd; - struct ib_uverbs_create_srq_resp resp; - - if (out_len < sizeof resp) - return -ENOSPC; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -3738,9 +3691,6 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs, struct ib_srq *srq; int ret; - if (out_len < sizeof resp) - return -ENOSPC; - if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; From c2a939fda468bb5c4144a64fd2b9cbdad323bf68 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:35 +0200 Subject: [PATCH 02/12] RDMA/uverbs: Use uverbs_attr_bundle to pass ucore for write/write_ex This creates a consistent way to access the two core buffers across write and write_ex handlers. Remove the open coded ucore conversion in the write/ex compatibility handlers. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 53 +++++++++------------------ drivers/infiniband/core/uverbs_main.c | 23 ++++++------ include/rdma/uverbs_ioctl.h | 1 + 3 files changed, 31 insertions(+), 46 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 5708abc0e4d4..0dd69133096d 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -891,13 +891,11 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, } static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore, struct ib_uverbs_ex_create_cq *cmd, size_t cmd_sz, int (*cb)(struct uverbs_attr_bundle *attrs, struct ib_ucq_object *obj, struct ib_uverbs_ex_create_cq_resp *resp, - struct ib_udata *ucore, void *context), void *context) { @@ -962,7 +960,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, cq->res.type = RDMA_RESTRACK_CQ; rdma_restrack_add(&cq->res); - ret = cb(attrs, obj, &resp, ucore, context); + ret = cb(attrs, obj, &resp, context); if (ret) goto err_cb; @@ -987,9 +985,9 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_create_cq_cb(struct uverbs_attr_bundle *attrs, struct ib_ucq_object *obj, struct ib_uverbs_ex_create_cq_resp *resp, - struct ib_udata *ucore, void *context) + void *context) { - if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base))) + if (ib_copy_to_udata(&attrs->ucore, &resp->base, sizeof(resp->base))) return -EFAULT; return 0; @@ -1000,23 +998,18 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, { struct ib_uverbs_create_cq cmd; struct ib_uverbs_ex_create_cq cmd_ex; - struct ib_uverbs_create_cq_resp resp; - struct ib_udata ucore; struct ib_ucq_object *obj; if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; - ib_uverbs_init_udata(&ucore, buf, u64_to_user_ptr(cmd.response), - sizeof(cmd), sizeof(resp)); - memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; cmd_ex.cqe = cmd.cqe; cmd_ex.comp_vector = cmd.comp_vector; cmd_ex.comp_channel = cmd.comp_channel; - obj = create_cq(attrs, &ucore, &cmd_ex, + obj = create_cq(attrs, &cmd_ex, offsetof(typeof(cmd_ex), comp_channel) + sizeof(cmd.comp_channel), ib_uverbs_create_cq_cb, NULL); @@ -1026,9 +1019,9 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_create_cq_cb(struct uverbs_attr_bundle *attrs, struct ib_ucq_object *obj, struct ib_uverbs_ex_create_cq_resp *resp, - struct ib_udata *ucore, void *context) + void *context) { - if (ib_copy_to_udata(ucore, resp, resp->response_length)) + if (ib_copy_to_udata(&attrs->ucore, resp, resp->response_length)) return -EFAULT; return 0; @@ -1059,7 +1052,7 @@ static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, sizeof(resp.response_length))) return -ENOSPC; - obj = create_cq(attrs, ucore, &cmd, min(ucore->inlen, sizeof(cmd)), + obj = create_cq(attrs, &cmd, min(ucore->inlen, sizeof(cmd)), ib_uverbs_ex_create_cq_cb, NULL); return PTR_ERR_OR_ZERO(obj); @@ -1144,7 +1137,7 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs, return -EINVAL; /* we copy a struct ib_uverbs_poll_cq_resp to user space */ - header_ptr = u64_to_user_ptr(cmd.response); + header_ptr = attrs->ucore.outbuf; data_ptr = header_ptr + sizeof resp; memset(&resp, 0, sizeof resp); @@ -1226,12 +1219,9 @@ static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs, } static int create_qp(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore, - struct ib_uverbs_ex_create_qp *cmd, - size_t cmd_sz, + struct ib_uverbs_ex_create_qp *cmd, size_t cmd_sz, int (*cb)(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp_resp *resp, - struct ib_udata *udata), + struct ib_uverbs_ex_create_qp_resp *resp), void *context) { struct ib_uqp_object *obj; @@ -1276,7 +1266,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, } if (cmd_sz > sizeof(*cmd) && - !ib_is_udata_cleared(ucore, sizeof(*cmd), + !ib_is_udata_cleared(&attrs->ucore, sizeof(*cmd), cmd_sz - sizeof(*cmd))) { ret = -EOPNOTSUPP; goto err_put; @@ -1456,7 +1446,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, resp.response_length = offsetof(typeof(resp), response_length) + sizeof(resp.response_length); - ret = cb(attrs, &resp, ucore); + ret = cb(attrs, &resp); if (ret) goto err_cb; @@ -1501,10 +1491,9 @@ static int create_qp(struct uverbs_attr_bundle *attrs, } static int ib_uverbs_create_qp_cb(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp_resp *resp, - struct ib_udata *ucore) + struct ib_uverbs_ex_create_qp_resp *resp) { - if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base))) + if (ib_copy_to_udata(&attrs->ucore, &resp->base, sizeof(resp->base))) return -EFAULT; return 0; @@ -1515,16 +1504,11 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, { struct ib_uverbs_create_qp cmd; struct ib_uverbs_ex_create_qp cmd_ex; - struct ib_udata ucore; - ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp); int err; if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; - ib_uverbs_init_udata(&ucore, buf, u64_to_user_ptr(cmd.response), - sizeof(cmd), resp_size); - memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; cmd_ex.pd_handle = cmd.pd_handle; @@ -1540,7 +1524,7 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, cmd_ex.qp_type = cmd.qp_type; cmd_ex.is_srq = cmd.is_srq; - err = create_qp(attrs, &ucore, &cmd_ex, + err = create_qp(attrs, &cmd_ex, offsetof(typeof(cmd_ex), is_srq) + sizeof(cmd.is_srq), ib_uverbs_create_qp_cb, NULL); @@ -1551,10 +1535,9 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, } static int ib_uverbs_ex_create_qp_cb(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp_resp *resp, - struct ib_udata *ucore) + struct ib_uverbs_ex_create_qp_resp *resp) { - if (ib_copy_to_udata(ucore, resp, resp->response_length)) + if (ib_copy_to_udata(&attrs->ucore, resp, resp->response_length)) return -EFAULT; return 0; @@ -1585,7 +1568,7 @@ static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, sizeof(resp.response_length))) return -ENOSPC; - err = create_qp(attrs, ucore, &cmd, + err = create_qp(attrs, &cmd, min(ucore->inlen, sizeof(cmd)), ib_uverbs_ex_create_qp_cb, NULL); diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index be049546cee2..762a6acbff80 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -695,6 +695,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if (!method_elm->is_ex) { size_t in_len = hdr.in_words * 4 - sizeof(hdr); size_t out_len = hdr.out_words * 4; + u64 response = 0; if (method_elm->has_udata) { bundle.driver_udata.inlen = @@ -710,8 +711,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, } if (method_elm->has_resp) { - u64 response; - /* * The macros check that if has_resp is set * then the command request structure starts @@ -737,23 +736,25 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, bundle.driver_udata.outbuf = NULL; } + ib_uverbs_init_udata_buf_or_null( + &bundle.ucore, buf, u64_to_user_ptr(response), + in_len, out_len); + ret = method_elm->handler(&bundle, buf, in_len, out_len); } else { - struct ib_udata ucore; - buf += sizeof(ex_hdr); - ib_uverbs_init_udata_buf_or_null(&ucore, buf, + ib_uverbs_init_udata_buf_or_null(&bundle.ucore, buf, u64_to_user_ptr(ex_hdr.response), hdr.in_words * 8, hdr.out_words * 8); - ib_uverbs_init_udata_buf_or_null(&bundle.driver_udata, - buf + ucore.inlen, - u64_to_user_ptr(ex_hdr.response) + ucore.outlen, - ex_hdr.provider_in_words * 8, - ex_hdr.provider_out_words * 8); + ib_uverbs_init_udata_buf_or_null( + &bundle.driver_udata, buf + bundle.ucore.inlen, + u64_to_user_ptr(ex_hdr.response) + bundle.ucore.outlen, + ex_hdr.provider_in_words * 8, + ex_hdr.provider_out_words * 8); - ret = method_elm->handler_ex(&bundle, &ucore); + ret = method_elm->handler_ex(&bundle, &bundle.ucore); } out_unlock: diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 8fc87079c2b8..9486a525afc1 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h @@ -647,6 +647,7 @@ struct uverbs_attr { struct uverbs_attr_bundle { struct ib_udata driver_udata; + struct ib_udata ucore; struct ib_uverbs_file *ufile; DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN); struct uverbs_attr attrs[]; From 931373a118acce816561f04dc9832b85172e65b8 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:36 +0200 Subject: [PATCH 03/12] RDMA/uverbs: Get rid of the 'callback' scheme in the compat path There is no reason for this. For response processing we simply need to copy, truncate, and zero fill the response into whatever output buffer was provided. Add a function uverbs_response() that does this consistently. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 120 +++++++++------------------ 1 file changed, 40 insertions(+), 80 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 0dd69133096d..6c9486f730fd 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -47,6 +47,35 @@ #include "uverbs.h" #include "core_priv.h" +/* + * Copy a response to userspace. If the provided 'resp' is larger than the + * user buffer it is silently truncated. If the user provided a larger buffer + * then the trailing portion is zero filled. + * + * These semantics are intended to support future extension of the output + * structures. + */ +static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp, + size_t resp_len) +{ + u8 __user *cur = attrs->ucore.outbuf + resp_len; + u8 __user *end = attrs->ucore.outbuf + attrs->ucore.outlen; + int ret; + + if (copy_to_user(attrs->ucore.outbuf, resp, + min(attrs->ucore.outlen, resp_len))) + return -EFAULT; + + /* Zero fill any extra memory that user space might have provided */ + for (; cur < end; cur++) { + ret = put_user(0, cur); + if (ret) + return ret; + } + + return 0; +} + static struct ib_uverbs_completion_event_file * _ib_uverbs_lookup_comp_file(s32 fd, const struct uverbs_attr_bundle *attrs) { @@ -892,12 +921,7 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, struct ib_uverbs_ex_create_cq *cmd, - size_t cmd_sz, - int (*cb)(struct uverbs_attr_bundle *attrs, - struct ib_ucq_object *obj, - struct ib_uverbs_ex_create_cq_resp *resp, - void *context), - void *context) + size_t cmd_sz) { struct ib_ucq_object *obj; struct ib_uverbs_completion_event_file *ev_file = NULL; @@ -953,14 +977,12 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, memset(&resp, 0, sizeof resp); resp.base.cq_handle = obj->uobject.id; resp.base.cqe = cq->cqe; - - resp.response_length = offsetof(typeof(resp), response_length) + - sizeof(resp.response_length); + resp.response_length = sizeof(resp); cq->res.type = RDMA_RESTRACK_CQ; rdma_restrack_add(&cq->res); - ret = cb(attrs, obj, &resp, context); + ret = uverbs_response(attrs, &resp, sizeof(resp)); if (ret) goto err_cb; @@ -982,17 +1004,6 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, return ERR_PTR(ret); } -static int ib_uverbs_create_cq_cb(struct uverbs_attr_bundle *attrs, - struct ib_ucq_object *obj, - struct ib_uverbs_ex_create_cq_resp *resp, - void *context) -{ - if (ib_copy_to_udata(&attrs->ucore, &resp->base, sizeof(resp->base))) - return -EFAULT; - - return 0; -} - static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { @@ -1011,22 +1022,10 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, obj = create_cq(attrs, &cmd_ex, offsetof(typeof(cmd_ex), comp_channel) + - sizeof(cmd.comp_channel), - ib_uverbs_create_cq_cb, NULL); + sizeof(cmd.comp_channel)); return PTR_ERR_OR_ZERO(obj); } -static int ib_uverbs_ex_create_cq_cb(struct uverbs_attr_bundle *attrs, - struct ib_ucq_object *obj, - struct ib_uverbs_ex_create_cq_resp *resp, - void *context) -{ - if (ib_copy_to_udata(&attrs->ucore, resp, resp->response_length)) - return -EFAULT; - - return 0; -} - static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { @@ -1052,9 +1051,7 @@ static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, sizeof(resp.response_length))) return -ENOSPC; - obj = create_cq(attrs, &cmd, min(ucore->inlen, sizeof(cmd)), - ib_uverbs_ex_create_cq_cb, NULL); - + obj = create_cq(attrs, &cmd, min(ucore->inlen, sizeof(cmd))); return PTR_ERR_OR_ZERO(obj); } @@ -1219,10 +1216,7 @@ static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs, } static int create_qp(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp *cmd, size_t cmd_sz, - int (*cb)(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp_resp *resp), - void *context) + struct ib_uverbs_ex_create_qp *cmd, size_t cmd_sz) { struct ib_uqp_object *obj; struct ib_device *device; @@ -1442,11 +1436,9 @@ static int create_qp(struct uverbs_attr_bundle *attrs, resp.base.max_recv_wr = attr.cap.max_recv_wr; resp.base.max_send_wr = attr.cap.max_send_wr; resp.base.max_inline_data = attr.cap.max_inline_data; + resp.response_length = sizeof(resp); - resp.response_length = offsetof(typeof(resp), response_length) + - sizeof(resp.response_length); - - ret = cb(attrs, &resp); + ret = uverbs_response(attrs, &resp, sizeof(resp)); if (ret) goto err_cb; @@ -1490,21 +1482,11 @@ static int create_qp(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_create_qp_cb(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp_resp *resp) -{ - if (ib_copy_to_udata(&attrs->ucore, &resp->base, sizeof(resp->base))) - return -EFAULT; - - return 0; -} - static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_create_qp cmd; struct ib_uverbs_ex_create_qp cmd_ex; - int err; if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; @@ -1524,23 +1506,8 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, cmd_ex.qp_type = cmd.qp_type; cmd_ex.is_srq = cmd.is_srq; - err = create_qp(attrs, &cmd_ex, - offsetof(typeof(cmd_ex), is_srq) + sizeof(cmd.is_srq), - ib_uverbs_create_qp_cb, NULL); - - if (err) - return err; - - return 0; -} - -static int ib_uverbs_ex_create_qp_cb(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp_resp *resp) -{ - if (ib_copy_to_udata(&attrs->ucore, resp, resp->response_length)) - return -EFAULT; - - return 0; + return create_qp(attrs, &cmd_ex, + offsetof(typeof(cmd_ex), is_srq) + sizeof(cmd.is_srq)); } static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, @@ -1568,14 +1535,7 @@ static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, sizeof(resp.response_length))) return -ENOSPC; - err = create_qp(attrs, &cmd, - min(ucore->inlen, sizeof(cmd)), - ib_uverbs_ex_create_qp_cb, NULL); - - if (err) - return err; - - return 0; + return create_qp(attrs, &cmd, min(ucore->inlen, sizeof(cmd))); } static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, From 9a0738575f2691d3a417fb5f83b6dcdaf0dcc36e Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:37 +0200 Subject: [PATCH 04/12] RDMA/uverbs: Use uverbs_response() for remaining response copying This function properly truncates and zero-fills the response which is the standard used by the ioctl uAPI when working with user data. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 133 +++++++++++---------------- 1 file changed, 52 insertions(+), 81 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 6c9486f730fd..79e6594f9309 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -162,10 +162,9 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs, goto err_fd; } - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_file; - } fd_install(resp.async_fd, filp); @@ -263,10 +262,7 @@ static int ib_uverbs_query_device(struct uverbs_attr_bundle *attrs, memset(&resp, 0, sizeof resp); copy_query_dev_fields(ucontext, &resp, &ucontext->device->attrs); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - return -EFAULT; - - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); } /* @@ -345,10 +341,7 @@ static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs, resp.link_layer = rdma_port_get_link_layer(ib_dev, cmd.port_num); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - return -EFAULT; - - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); } static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, @@ -385,10 +378,9 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, pd->res.type = RDMA_RESTRACK_PD; rdma_restrack_add(&pd->res); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_copy; - } return uobj_alloc_commit(uobj); @@ -575,10 +567,9 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs, atomic_inc(&xrcd->usecnt); } - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_copy; - } if (f.file) fdput(f); @@ -707,10 +698,9 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs, resp.rkey = mr->rkey; resp.mr_handle = uobj->id; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_copy; - } uobj_put_obj_read(pd); @@ -793,10 +783,7 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs, resp.lkey = mr->lkey; resp.rkey = mr->rkey; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof(resp))) - ret = -EFAULT; - else - ret = 0; + ret = uverbs_response(attrs, &resp, sizeof(resp)); put_uobj_pd: if (cmd.flags & IB_MR_REREG_PD) @@ -860,10 +847,9 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs, resp.rkey = mw->rkey; resp.mw_handle = uobj->id; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof(resp))) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_copy; - } uobj_put_obj_read(pd); return uobj_alloc_commit(uobj); @@ -897,6 +883,7 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, struct ib_uobject *uobj; struct ib_uverbs_completion_event_file *ev_file; struct ib_device *ib_dev; + int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -911,9 +898,10 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, uobj); ib_uverbs_init_event_queue(&ev_file->ev_queue); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) { uobj_alloc_abort(uobj); - return -EFAULT; + return ret; } return uobj_alloc_commit(uobj); @@ -1076,9 +1064,7 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs, resp.cqe = cq->cqe; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp.cqe)) - ret = -EFAULT; - + ret = uverbs_response(attrs, &resp, sizeof(resp)); out: uobj_put_obj_read(cq); @@ -1209,10 +1195,7 @@ static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs, uobj_put_destroy(uobj); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - return -EFAULT; - - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); } static int create_qp(struct uverbs_attr_bundle *attrs, @@ -1593,10 +1576,9 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, resp.qpn = qp->qp_num; resp.qp_handle = obj->uevent.uobject.id; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_destroy; - } obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject); atomic_inc(&obj->uxrcd->refcnt); @@ -1703,8 +1685,7 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs, resp.max_inline_data = init_attr->cap.max_inline_data; resp.sq_sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); out: kfree(attr); @@ -1979,10 +1960,7 @@ static int ib_uverbs_destroy_qp(struct uverbs_attr_bundle *attrs, uobj_put_destroy(uobj); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - return -EFAULT; - - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); } static void *alloc_wr(size_t wr_size, __u32 num_sge) @@ -2006,7 +1984,7 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, struct ib_qp *qp; int i, sg_ind; int is_ud; - ssize_t ret = -EINVAL; + int ret, ret2; size_t next_size; if (copy_from_user(&cmd, buf, sizeof cmd)) @@ -2162,8 +2140,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, break; } - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - ret = -EFAULT; + ret2 = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret2) + ret = ret2; out_put: uobj_put_obj_read(qp); @@ -2282,7 +2261,7 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs, struct ib_recv_wr *wr, *next; const struct ib_recv_wr *bad_wr; struct ib_qp *qp; - ssize_t ret = -EINVAL; + int ret, ret2; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -2294,8 +2273,10 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs, return PTR_ERR(wr); qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); - if (!qp) + if (!qp) { + ret = -EINVAL; goto out; + } resp.bad_wr = 0; ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr); @@ -2309,9 +2290,9 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs, } } - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - ret = -EFAULT; - + ret2 = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret2) + ret = ret2; out: while (wr) { next = wr->next; @@ -2331,7 +2312,7 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs, struct ib_recv_wr *wr, *next; const struct ib_recv_wr *bad_wr; struct ib_srq *srq; - ssize_t ret = -EINVAL; + int ret, ret2; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; @@ -2343,8 +2324,10 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs, return PTR_ERR(wr); srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); - if (!srq) + if (!srq) { + ret = -EINVAL; goto out; + } resp.bad_wr = 0; ret = srq->device->post_srq_recv(srq, wr, &bad_wr); @@ -2358,8 +2341,9 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs, break; } - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - ret = -EFAULT; + ret2 = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret2) + ret = ret2; out: while (wr) { @@ -2431,10 +2415,9 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs, resp.ah_handle = uobj->id; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_copy; - } uobj_put_obj_read(pd); return uobj_alloc_commit(uobj); @@ -2962,8 +2945,7 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, resp.max_wr = wq_init_attr.max_wr; resp.wqn = wq->wq_num; resp.response_length = required_resp_len; - err = ib_copy_to_udata(ucore, - &resp, resp.response_length); + err = uverbs_response(attrs, &resp, sizeof(resp)); if (err) goto err_copy; @@ -3025,7 +3007,7 @@ static int ib_uverbs_ex_destroy_wq(struct uverbs_attr_bundle *attrs, uobj_put_destroy(uobj); - return ib_copy_to_udata(ucore, &resp, resp.response_length); + return uverbs_response(attrs, &resp, sizeof(resp)); } static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs, @@ -3186,8 +3168,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, resp.ind_tbl_num = rwq_ind_tbl->ind_tbl_num; resp.response_length = required_resp_len; - err = ib_copy_to_udata(ucore, - &resp, resp.response_length); + err = uverbs_response(attrs, &resp, sizeof(resp)); if (err) goto err_copy; @@ -3384,8 +3365,7 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs, memset(&resp, 0, sizeof(resp)); resp.flow_handle = uobj->id; - err = ib_copy_to_udata(ucore, - &resp, sizeof(resp)); + err = uverbs_response(attrs, &resp, sizeof(resp)); if (err) goto err_copy; @@ -3530,11 +3510,9 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, if (cmd->srq_type == IB_SRQT_XRC) resp.srqn = srq->ext.xrc.srq_num; - if (copy_to_user(u64_to_user_ptr(cmd->response), - &resp, sizeof resp)) { - ret = -EFAULT; + ret = uverbs_response(attrs, &resp, sizeof(resp)); + if (ret) goto err_copy; - } if (cmd->srq_type == IB_SRQT_XRC) uobj_put_read(xrcd_uobj); @@ -3654,10 +3632,7 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs, resp.max_sge = attr.max_sge; resp.srq_limit = attr.srq_limit; - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp)) - return -EFAULT; - - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); } static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs, @@ -3682,10 +3657,7 @@ static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs, uobj_put_destroy(uobj); - if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof(resp))) - return -EFAULT; - - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); } static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, @@ -3807,8 +3779,7 @@ static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, resp.max_dm_size = attr.max_dm_size; resp.response_length += sizeof(resp.max_dm_size); end: - err = ib_copy_to_udata(ucore, &resp, resp.response_length); - return err; + return uverbs_response(attrs, &resp, sizeof(resp)); } static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs, From 3c2c20947ddbb897a1459f149509ac03e35043e1 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:38 +0200 Subject: [PATCH 05/12] RDMA/uverbs: Use uverbs_request() for request copying This function properly zero-extends, and zero-checks if the user buffer is not the same size as the kernel command struct. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 199 ++++++++++++++++++--------- 1 file changed, 135 insertions(+), 64 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 79e6594f9309..173b8e83782e 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -76,6 +76,30 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp, return 0; } +/* + * Copy a request from userspace. If the provided 'req' is larger than the + * user buffer then the user buffer is zero extended into the 'req'. If 'req' + * is smaller than the user buffer then the uncopied bytes in the user buffer + * must be zero. + */ +static int uverbs_request(struct uverbs_attr_bundle *attrs, void *req, + size_t req_len) +{ + if (copy_from_user(req, attrs->ucore.inbuf, + min(attrs->ucore.inlen, req_len))) + return -EFAULT; + + if (attrs->ucore.inlen < req_len) { + memset(req + attrs->ucore.inlen, 0, + req_len - attrs->ucore.inlen); + } else if (attrs->ucore.inlen > req_len) { + if (!ib_is_buffer_cleared(attrs->ucore.inbuf + req_len, + attrs->ucore.inlen - req_len)) + return -EOPNOTSUPP; + } + return 0; +} + static struct ib_uverbs_completion_event_file * _ib_uverbs_lookup_comp_file(s32 fd, const struct uverbs_attr_bundle *attrs) { @@ -107,8 +131,9 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs, struct ib_device *ib_dev; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; mutex_lock(&file->ucontext_lock); ib_dev = srcu_dereference(file->device->ib_dev, @@ -251,13 +276,15 @@ static int ib_uverbs_query_device(struct uverbs_attr_bundle *attrs, struct ib_uverbs_query_device cmd; struct ib_uverbs_query_device_resp resp; struct ib_ucontext *ucontext; + int ret; ucontext = ib_uverbs_get_ucontext(attrs); if (IS_ERR(ucontext)) return PTR_ERR(ucontext); - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; memset(&resp, 0, sizeof resp); copy_query_dev_fields(ucontext, &resp, &ucontext->device->attrs); @@ -301,8 +328,9 @@ static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs, return PTR_ERR(ucontext); ib_dev = ucontext->device; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; ret = ib_query_port(ib_dev, cmd.port_num, &attr); if (ret) @@ -354,8 +382,9 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_alloc(UVERBS_OBJECT_PD, attrs, &ib_dev); if (IS_ERR(uobj)) @@ -396,9 +425,11 @@ static int ib_uverbs_dealloc_pd(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_dealloc_pd cmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; return uobj_perform_destroy(UVERBS_OBJECT_PD, cmd.pd_handle, attrs); } @@ -502,8 +533,9 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs, int new_xrcd = 0; struct ib_device *ib_dev; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; mutex_lock(&ibudev->xrcd_tree_mutex); @@ -604,9 +636,11 @@ static int ib_uverbs_close_xrcd(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_close_xrcd cmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; return uobj_perform_destroy(UVERBS_OBJECT_XRCD, cmd.xrcd_handle, attrs); } @@ -647,8 +681,9 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) return -EINVAL; @@ -728,8 +763,9 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs, int ret; struct ib_uobject *uobj; - if (copy_from_user(&cmd, buf, sizeof(cmd))) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags) return -EINVAL; @@ -799,9 +835,11 @@ static int ib_uverbs_dereg_mr(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_dereg_mr cmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; return uobj_perform_destroy(UVERBS_OBJECT_MR, cmd.mr_handle, attrs); } @@ -817,8 +855,9 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (copy_from_user(&cmd, buf, sizeof(cmd))) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_alloc(UVERBS_OBJECT_MW, attrs, &ib_dev); if (IS_ERR(uobj)) @@ -867,9 +906,11 @@ static int ib_uverbs_dealloc_mw(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_dealloc_mw cmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof(cmd))) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; return uobj_perform_destroy(UVERBS_OBJECT_MW, cmd.mw_handle, attrs); } @@ -885,8 +926,9 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, struct ib_device *ib_dev; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_alloc(UVERBS_OBJECT_COMP_CHANNEL, attrs, &ib_dev); if (IS_ERR(uobj)) @@ -998,9 +1040,11 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, struct ib_uverbs_create_cq cmd; struct ib_uverbs_ex_create_cq cmd_ex; struct ib_ucq_object *obj; + int ret; - if (copy_from_user(&cmd, buf, sizeof(cmd))) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; @@ -1051,8 +1095,9 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs, struct ib_cq *cq; int ret = -EINVAL; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); if (!cq) @@ -1112,8 +1157,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs, struct ib_wc wc; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); if (!cq) @@ -1157,9 +1203,11 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs, { struct ib_uverbs_req_notify_cq cmd; struct ib_cq *cq; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); if (!cq) @@ -1180,9 +1228,11 @@ static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs, struct ib_uverbs_destroy_cq_resp resp; struct ib_uobject *uobj; struct ib_ucq_object *obj; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_get_destroy(UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); if (IS_ERR(uobj)) @@ -1470,9 +1520,11 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, { struct ib_uverbs_create_qp cmd; struct ib_uverbs_ex_create_qp cmd_ex; + int ret; - if (copy_from_user(&cmd, buf, sizeof(cmd))) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; @@ -1534,8 +1586,9 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; obj = (struct ib_uqp_object *)uobj_alloc(UVERBS_OBJECT_QP, attrs, &ib_dev); @@ -1628,8 +1681,9 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs, struct ib_qp_init_attr *init_attr; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; attr = kmalloc(sizeof *attr, GFP_KERNEL); init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL); @@ -1894,9 +1948,11 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_ex_modify_qp cmd = {}; + int ret; - if (copy_from_user(&cmd.base, buf, sizeof(cmd.base))) - return -EFAULT; + ret = uverbs_request(attrs, &cmd.base, sizeof(cmd.base)); + if (ret) + return ret; if (cmd.base.attr_mask & ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1)) @@ -1946,9 +2002,11 @@ static int ib_uverbs_destroy_qp(struct uverbs_attr_bundle *attrs, struct ib_uverbs_destroy_qp_resp resp; struct ib_uobject *uobj; struct ib_uqp_object *obj; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_get_destroy(UVERBS_OBJECT_QP, cmd.qp_handle, attrs); if (IS_ERR(uobj)) @@ -2367,8 +2425,9 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs, int ret; struct ib_device *ib_dev; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_alloc(UVERBS_OBJECT_AH, attrs, &ib_dev); if (IS_ERR(uobj)) @@ -2437,9 +2496,11 @@ static int ib_uverbs_destroy_ah(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_destroy_ah cmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; return uobj_perform_destroy(UVERBS_OBJECT_AH, cmd.ah_handle, attrs); } @@ -2454,8 +2515,9 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs, struct ib_uverbs_mcast_entry *mcast; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); if (!qp) @@ -2504,8 +2566,9 @@ static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs, int ret = -EINVAL; bool found = false; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); if (!qp) @@ -3549,9 +3612,11 @@ static int ib_uverbs_create_srq(struct uverbs_attr_bundle *attrs, { struct ib_uverbs_create_srq cmd; struct ib_uverbs_create_xsrq xcmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; memset(&xcmd, 0, sizeof(xcmd)); xcmd.response = cmd.response; @@ -3570,9 +3635,11 @@ static int ib_uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, int out_len) { struct ib_uverbs_create_xsrq cmd; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; return __uverbs_create_xsrq(attrs, &cmd, &attrs->driver_udata); } @@ -3585,8 +3652,9 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs, struct ib_srq_attr attr; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); if (!srq) @@ -3612,8 +3680,9 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs, struct ib_srq *srq; int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); if (!srq) @@ -3643,9 +3712,11 @@ static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs, struct ib_uverbs_destroy_srq_resp resp; struct ib_uobject *uobj; struct ib_uevent_object *obj; + int ret; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; uobj = uobj_get_destroy(UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); if (IS_ERR(uobj)) From 29a29d18523235e749916a0154435f26f3238639 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:39 +0200 Subject: [PATCH 06/12] RDMA/uverbs: Use uverbs_request() and core for write_ex handlers The write_ex handlers have this horrible boilerplate in every function to do the zero extend/zero check and min size checks. This is now handled in the core code via the meta-data, and the zero checks are handled by uverbs_request(). Replace all the occurrences. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 185 +++++++-------------------- 1 file changed, 46 insertions(+), 139 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 173b8e83782e..7f8b0a7dcb17 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -100,6 +100,18 @@ static int uverbs_request(struct uverbs_attr_bundle *attrs, void *req, return 0; } +/* + * Generate the value for the 'response_length' protocol used by write_ex. + * This is the number of bytes the kernel actually wrote. Userspace can use + * this to detect what structure members in the response the kernel + * understood. + */ +static u32 uverbs_response_length(struct uverbs_attr_bundle *attrs, + size_t resp_len) +{ + return min_t(size_t, attrs->ucore.outlen, resp_len); +} + static struct ib_uverbs_completion_event_file * _ib_uverbs_lookup_comp_file(s32 fd, const struct uverbs_attr_bundle *attrs) { @@ -1007,7 +1019,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, memset(&resp, 0, sizeof resp); resp.base.cq_handle = obj->uobject.id; resp.base.cqe = cq->cqe; - resp.response_length = sizeof(resp); + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); cq->res.type = RDMA_RESTRACK_CQ; rdma_restrack_add(&cq->res); @@ -1061,17 +1073,13 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_create_cq_resp resp; struct ib_uverbs_ex_create_cq cmd; struct ib_ucq_object *obj; - int err; + int ret; - if (ucore->inlen < sizeof(cmd)) - return -EINVAL; - - err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); - if (err) - return err; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; if (cmd.comp_mask) return -EINVAL; @@ -1079,10 +1087,6 @@ static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, if (cmd.reserved) return -EINVAL; - if (ucore->outlen < (offsetof(typeof(resp), response_length) + - sizeof(resp.response_length))) - return -ENOSPC; - obj = create_cq(attrs, &cmd, min(ucore->inlen, sizeof(cmd))); return PTR_ERR_OR_ZERO(obj); } @@ -1292,13 +1296,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs, attr.rwq_ind_tbl = ind_tbl; } - if (cmd_sz > sizeof(*cmd) && - !ib_is_udata_cleared(&attrs->ucore, sizeof(*cmd), - cmd_sz - sizeof(*cmd))) { - ret = -EOPNOTSUPP; - goto err_put; - } - if (ind_tbl && (cmd->max_recv_wr || cmd->max_recv_sge || cmd->is_srq)) { ret = -EINVAL; goto err_put; @@ -1469,7 +1466,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, resp.base.max_recv_wr = attr.cap.max_recv_wr; resp.base.max_send_wr = attr.cap.max_send_wr; resp.base.max_inline_data = attr.cap.max_inline_data; - resp.response_length = sizeof(resp); + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); ret = uverbs_response(attrs, &resp, sizeof(resp)); if (ret) @@ -1548,17 +1545,12 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_create_qp_resp resp; - struct ib_uverbs_ex_create_qp cmd = {0}; - int err; + struct ib_uverbs_ex_create_qp cmd; + int ret; - if (ucore->inlen < (offsetof(typeof(cmd), comp_mask) + - sizeof(cmd.comp_mask))) - return -EINVAL; - - err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); - if (err) - return err; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; if (cmd.comp_mask & ~IB_UVERBS_CREATE_QP_SUP_COMP_MASK) return -EINVAL; @@ -1566,10 +1558,6 @@ static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, if (cmd.reserved) return -EINVAL; - if (ucore->outlen < (offsetof(typeof(resp), response_length) + - sizeof(resp.response_length))) - return -ENOSPC; - return create_qp(attrs, &cmd, min(ucore->inlen, sizeof(cmd))); } @@ -1947,7 +1935,7 @@ static int modify_qp(struct uverbs_attr_bundle *attrs, static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs, const char __user *buf, int in_len, int out_len) { - struct ib_uverbs_ex_modify_qp cmd = {}; + struct ib_uverbs_ex_modify_qp cmd; int ret; ret = uverbs_request(attrs, &cmd.base, sizeof(cmd.base)); @@ -1964,35 +1952,24 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_modify_qp cmd = {}; + struct ib_uverbs_ex_modify_qp cmd; int ret; + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); + if (ret) + return ret; + /* * Last bit is reserved for extending the attr_mask by * using another field. */ BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31)); - if (ucore->inlen < sizeof(cmd.base)) - return -EINVAL; - - ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); - if (ret) - return ret; - if (cmd.base.attr_mask & ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; - if (ucore->inlen > sizeof(cmd)) { - if (!ib_is_udata_cleared(ucore, sizeof(cmd), - ucore->inlen - sizeof(cmd))) - return -EOPNOTSUPP; - } - - ret = modify_qp(attrs, &cmd); - - return ret; + return modify_qp(attrs, &cmd); } static int ib_uverbs_destroy_qp(struct uverbs_attr_bundle *attrs, @@ -2921,7 +2898,7 @@ static int kern_spec_to_ib_spec(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_create_wq cmd = {}; + struct ib_uverbs_ex_create_wq cmd; struct ib_uverbs_ex_create_wq_resp resp = {}; struct ib_uwq_object *obj; int err = 0; @@ -2929,25 +2906,9 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, struct ib_pd *pd; struct ib_wq *wq; struct ib_wq_init_attr wq_init_attr = {}; - size_t required_cmd_sz; - size_t required_resp_len; struct ib_device *ib_dev; - required_cmd_sz = offsetof(typeof(cmd), max_sge) + sizeof(cmd.max_sge); - required_resp_len = offsetof(typeof(resp), wqn) + sizeof(resp.wqn); - - if (ucore->inlen < required_cmd_sz) - return -EINVAL; - - if (ucore->outlen < required_resp_len) - return -ENOSPC; - - if (ucore->inlen > sizeof(cmd) && - !ib_is_udata_cleared(ucore, sizeof(cmd), - ucore->inlen - sizeof(cmd))) - return -EOPNOTSUPP; - - err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); + err = uverbs_request(attrs, &cmd, sizeof(cmd)); if (err) return err; @@ -2977,9 +2938,7 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, wq_init_attr.wq_context = attrs->ufile; wq_init_attr.wq_type = cmd.wq_type; wq_init_attr.event_handler = ib_uverbs_wq_event_handler; - if (ucore->inlen >= (offsetof(typeof(cmd), create_flags) + - sizeof(cmd.create_flags))) - wq_init_attr.create_flags = cmd.create_flags; + wq_init_attr.create_flags = cmd.create_flags; obj->uevent.events_reported = 0; INIT_LIST_HEAD(&obj->uevent.event_list); @@ -3007,7 +2966,7 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, resp.max_sge = wq_init_attr.max_sge; resp.max_wr = wq_init_attr.max_wr; resp.wqn = wq->wq_num; - resp.response_length = required_resp_len; + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); err = uverbs_response(attrs, &resp, sizeof(resp)); if (err) goto err_copy; @@ -3031,36 +2990,20 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_destroy_wq(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_destroy_wq cmd = {}; + struct ib_uverbs_ex_destroy_wq cmd; struct ib_uverbs_ex_destroy_wq_resp resp = {}; struct ib_uobject *uobj; struct ib_uwq_object *obj; - size_t required_cmd_sz; - size_t required_resp_len; int ret; - required_cmd_sz = offsetof(typeof(cmd), wq_handle) + sizeof(cmd.wq_handle); - required_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved); - - if (ucore->inlen < required_cmd_sz) - return -EINVAL; - - if (ucore->outlen < required_resp_len) - return -ENOSPC; - - if (ucore->inlen > sizeof(cmd) && - !ib_is_udata_cleared(ucore, sizeof(cmd), - ucore->inlen - sizeof(cmd))) - return -EOPNOTSUPP; - - ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) return ret; if (cmd.comp_mask) return -EOPNOTSUPP; - resp.response_length = required_resp_len; + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); uobj = uobj_get_destroy(UVERBS_OBJECT_WQ, cmd.wq_handle, attrs); if (IS_ERR(uobj)) return PTR_ERR(uobj); @@ -3076,22 +3019,12 @@ static int ib_uverbs_ex_destroy_wq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_modify_wq cmd = {}; + struct ib_uverbs_ex_modify_wq cmd; struct ib_wq *wq; struct ib_wq_attr wq_attr = {}; - size_t required_cmd_sz; int ret; - required_cmd_sz = offsetof(typeof(cmd), curr_wq_state) + sizeof(cmd.curr_wq_state); - if (ucore->inlen < required_cmd_sz) - return -EINVAL; - - if (ucore->inlen > sizeof(cmd) && - !ib_is_udata_cleared(ucore, sizeof(cmd), - ucore->inlen - sizeof(cmd))) - return -EOPNOTSUPP; - - ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) return ret; @@ -3229,7 +3162,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, resp.ind_tbl_handle = uobj->id; resp.ind_tbl_num = rwq_ind_tbl->ind_tbl_num; - resp.response_length = required_resp_len; + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); err = uverbs_response(attrs, &resp, sizeof(resp)); if (err) @@ -3258,21 +3191,10 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_destroy_rwq_ind_table(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_destroy_rwq_ind_table cmd = {}; - int ret; - size_t required_cmd_sz; + struct ib_uverbs_ex_destroy_rwq_ind_table cmd; + int ret; - required_cmd_sz = offsetof(typeof(cmd), ind_tbl_handle) + sizeof(cmd.ind_tbl_handle); - - if (ucore->inlen < required_cmd_sz) - return -EINVAL; - - if (ucore->inlen > sizeof(cmd) && - !ib_is_udata_cleared(ucore, sizeof(cmd), - ucore->inlen - sizeof(cmd))) - return -EOPNOTSUPP; - - ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) return ret; @@ -3460,10 +3382,7 @@ static int ib_uverbs_ex_destroy_flow(struct uverbs_attr_bundle *attrs, struct ib_uverbs_destroy_flow cmd; int ret; - if (ucore->inlen < sizeof(cmd)) - return -EINVAL; - - ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) return ret; @@ -3856,23 +3775,11 @@ static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_modify_cq cmd = {}; + struct ib_uverbs_ex_modify_cq cmd; struct ib_cq *cq; - size_t required_cmd_sz; int ret; - required_cmd_sz = offsetof(typeof(cmd), reserved) + - sizeof(cmd.reserved); - if (ucore->inlen < required_cmd_sz) - return -EINVAL; - - /* sanity checks */ - if (ucore->inlen > sizeof(cmd) && - !ib_is_udata_cleared(ucore, sizeof(cmd), - ucore->inlen - sizeof(cmd))) - return -EOPNOTSUPP; - - ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); + ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) return ret; From 40efca7a46a04223e6792fbe23ba337f54cff794 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:40 +0200 Subject: [PATCH 07/12] RDMA/uverbs: Fill in the response for IB_USER_VERBS_EX_CMD_MODIFY_QP A response struct was defined, and userspace is providing it (but not checking it). Fill it in and write it out. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 7f8b0a7dcb17..c605412708b8 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1953,6 +1953,9 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { struct ib_uverbs_ex_modify_qp cmd; + struct ib_uverbs_ex_modify_qp_resp resp = { + .response_length = uverbs_response_length(attrs, sizeof(resp)) + }; int ret; ret = uverbs_request(attrs, &cmd, sizeof(cmd)); @@ -1969,7 +1972,11 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs, ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; - return modify_qp(attrs, &cmd); + ret = modify_qp(attrs, &cmd); + if (ret) + return ret; + + return uverbs_response(attrs, &resp, sizeof(resp)); } static int ib_uverbs_destroy_qp(struct uverbs_attr_bundle *attrs, From 7eebced1bae034e11a86c454383b24715eb087b6 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:41 +0200 Subject: [PATCH 08/12] RDMA/uverbs: Simplify ib_uverbs_ex_query_device We truncate the response structure if there is not enough room in the user buffer so there is no reason to have all the mess with finely managing response_length. Just fully fill the attrs and truncate on copy. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 64 ++-------------------------- 1 file changed, 4 insertions(+), 60 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index c605412708b8..3cc746639c7b 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -3660,7 +3660,7 @@ static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_query_device_resp resp = { {0} }; + struct ib_uverbs_ex_query_device_resp resp = {}; struct ib_uverbs_ex_query_device cmd; struct ib_device_attr attr = {0}; struct ib_ucontext *ucontext; @@ -3672,10 +3672,7 @@ static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, return PTR_ERR(ucontext); ib_dev = ucontext->device; - if (ucore->inlen < sizeof(cmd)) - return -EINVAL; - - err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); + err = uverbs_request(attrs, &cmd, sizeof(cmd)); if (err) return err; @@ -3685,20 +3682,12 @@ static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, if (cmd.reserved) return -EINVAL; - resp.response_length = offsetof(typeof(resp), odp_caps); - - if (ucore->outlen < resp.response_length) - return -ENOSPC; - err = ib_dev->query_device(ib_dev, &attr, &attrs->driver_udata); if (err) return err; copy_query_dev_fields(ucontext, &resp.base, &attr); - if (ucore->outlen < resp.response_length + sizeof(resp.odp_caps)) - goto end; - #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING resp.odp_caps.general_caps = attr.odp_caps.general_caps; resp.odp_caps.per_transport_caps.rc_odp_caps = @@ -3708,74 +3697,29 @@ static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, resp.odp_caps.per_transport_caps.ud_odp_caps = attr.odp_caps.per_transport_caps.ud_odp_caps; #endif - resp.response_length += sizeof(resp.odp_caps); - - if (ucore->outlen < resp.response_length + sizeof(resp.timestamp_mask)) - goto end; resp.timestamp_mask = attr.timestamp_mask; - resp.response_length += sizeof(resp.timestamp_mask); - - if (ucore->outlen < resp.response_length + sizeof(resp.hca_core_clock)) - goto end; - resp.hca_core_clock = attr.hca_core_clock; - resp.response_length += sizeof(resp.hca_core_clock); - - if (ucore->outlen < resp.response_length + sizeof(resp.device_cap_flags_ex)) - goto end; - resp.device_cap_flags_ex = attr.device_cap_flags; - resp.response_length += sizeof(resp.device_cap_flags_ex); - - if (ucore->outlen < resp.response_length + sizeof(resp.rss_caps)) - goto end; - resp.rss_caps.supported_qpts = attr.rss_caps.supported_qpts; resp.rss_caps.max_rwq_indirection_tables = attr.rss_caps.max_rwq_indirection_tables; resp.rss_caps.max_rwq_indirection_table_size = attr.rss_caps.max_rwq_indirection_table_size; - - resp.response_length += sizeof(resp.rss_caps); - - if (ucore->outlen < resp.response_length + sizeof(resp.max_wq_type_rq)) - goto end; - resp.max_wq_type_rq = attr.max_wq_type_rq; - resp.response_length += sizeof(resp.max_wq_type_rq); - - if (ucore->outlen < resp.response_length + sizeof(resp.raw_packet_caps)) - goto end; - resp.raw_packet_caps = attr.raw_packet_caps; - resp.response_length += sizeof(resp.raw_packet_caps); - - if (ucore->outlen < resp.response_length + sizeof(resp.tm_caps)) - goto end; - resp.tm_caps.max_rndv_hdr_size = attr.tm_caps.max_rndv_hdr_size; resp.tm_caps.max_num_tags = attr.tm_caps.max_num_tags; resp.tm_caps.max_ops = attr.tm_caps.max_ops; resp.tm_caps.max_sge = attr.tm_caps.max_sge; resp.tm_caps.flags = attr.tm_caps.flags; - resp.response_length += sizeof(resp.tm_caps); - - if (ucore->outlen < resp.response_length + sizeof(resp.cq_moderation_caps)) - goto end; - resp.cq_moderation_caps.max_cq_moderation_count = attr.cq_caps.max_cq_moderation_count; resp.cq_moderation_caps.max_cq_moderation_period = attr.cq_caps.max_cq_moderation_period; - resp.response_length += sizeof(resp.cq_moderation_caps); - - if (ucore->outlen < resp.response_length + sizeof(resp.max_dm_size)) - goto end; - resp.max_dm_size = attr.max_dm_size; - resp.response_length += sizeof(resp.max_dm_size); -end: + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); + return uverbs_response(attrs, &resp, sizeof(resp)); } From 335708c751c1462b674892212e965fdde4c9b0d9 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:42 +0200 Subject: [PATCH 09/12] RDMA/uverbs: Add a simple iterator interface for reading the command Several methods have a command with a trailing flex array, and they all open code some extraction scheme. Centralize this into a simple iterator API. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 113 +++++++++++++++------------ 1 file changed, 65 insertions(+), 48 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 3cc746639c7b..a89b8442ca32 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -112,6 +112,51 @@ static u32 uverbs_response_length(struct uverbs_attr_bundle *attrs, return min_t(size_t, attrs->ucore.outlen, resp_len); } +/* + * The iterator version of the request interface is for handlers that need to + * step over a flex array at the end of a command header. + */ +struct uverbs_req_iter { + const void __user *cur; + const void __user *end; +}; + +static int uverbs_request_start(struct uverbs_attr_bundle *attrs, + struct uverbs_req_iter *iter, + void *req, + size_t req_len) +{ + if (attrs->ucore.inlen < req_len) + return -ENOSPC; + + if (copy_from_user(req, attrs->ucore.inbuf, req_len)) + return -EFAULT; + + iter->cur = attrs->ucore.inbuf + req_len; + iter->end = attrs->ucore.inbuf + attrs->ucore.inlen; + return 0; +} + +static int uverbs_request_next(struct uverbs_req_iter *iter, void *val, + size_t len) +{ + if (iter->cur + len > iter->end) + return -ENOSPC; + + if (copy_from_user(val, iter->cur, len)) + return -EFAULT; + + iter->cur += len; + return 0; +} + +static int uverbs_request_finish(struct uverbs_req_iter *iter) +{ + if (!ib_is_buffer_cleared(iter->cur, iter->end - iter->cur)) + return -EOPNOTSUPP; + return 0; +} + static struct ib_uverbs_completion_event_file * _ib_uverbs_lookup_comp_file(s32 fd, const struct uverbs_attr_bundle *attrs) { @@ -3060,10 +3105,10 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs, static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, struct ib_udata *ucore) { - struct ib_uverbs_ex_create_rwq_ind_table cmd = {}; + struct ib_uverbs_ex_create_rwq_ind_table cmd; struct ib_uverbs_ex_create_rwq_ind_table_resp resp = {}; struct ib_uobject *uobj; - int err = 0; + int err; struct ib_rwq_ind_table_init_attr init_attr = {}; struct ib_rwq_ind_table *rwq_ind_tbl; struct ib_wq **wqs = NULL; @@ -3071,27 +3116,13 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, struct ib_wq *wq = NULL; int i, j, num_read_wqs; u32 num_wq_handles; - u32 expected_in_size; - size_t required_cmd_sz_header; - size_t required_resp_len; + struct uverbs_req_iter iter; struct ib_device *ib_dev; - required_cmd_sz_header = offsetof(typeof(cmd), log_ind_tbl_size) + sizeof(cmd.log_ind_tbl_size); - required_resp_len = offsetof(typeof(resp), ind_tbl_num) + sizeof(resp.ind_tbl_num); - - if (ucore->inlen < required_cmd_sz_header) - return -EINVAL; - - if (ucore->outlen < required_resp_len) - return -ENOSPC; - - err = ib_copy_from_udata(&cmd, ucore, required_cmd_sz_header); + err = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd)); if (err) return err; - ucore->inbuf += required_cmd_sz_header; - ucore->inlen -= required_cmd_sz_header; - if (cmd.comp_mask) return -EOPNOTSUPP; @@ -3099,26 +3130,17 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, return -EINVAL; num_wq_handles = 1 << cmd.log_ind_tbl_size; - expected_in_size = num_wq_handles * sizeof(__u32); - if (num_wq_handles == 1) - /* input size for wq handles is u64 aligned */ - expected_in_size += sizeof(__u32); - - if (ucore->inlen < expected_in_size) - return -EINVAL; - - if (ucore->inlen > expected_in_size && - !ib_is_udata_cleared(ucore, expected_in_size, - ucore->inlen - expected_in_size)) - return -EOPNOTSUPP; - wqs_handles = kcalloc(num_wq_handles, sizeof(*wqs_handles), GFP_KERNEL); if (!wqs_handles) return -ENOMEM; - err = ib_copy_from_udata(wqs_handles, ucore, - num_wq_handles * sizeof(__u32)); + err = uverbs_request_next(&iter, wqs_handles, + num_wq_handles * sizeof(__u32)); + if (err) + goto err_free; + + err = uverbs_request_finish(&iter); if (err) goto err_free; @@ -3224,24 +3246,16 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs, struct ib_qp *qp; struct ib_uflow_resources *uflow_res; struct ib_uverbs_flow_spec_hdr *kern_spec; - int err = 0; + struct uverbs_req_iter iter; + int err; void *ib_spec; int i; struct ib_device *ib_dev; - if (ucore->inlen < sizeof(cmd)) - return -EINVAL; - - if (ucore->outlen < sizeof(resp)) - return -ENOSPC; - - err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); + err = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd)); if (err) return err; - ucore->inbuf += sizeof(cmd); - ucore->inlen -= sizeof(cmd); - if (cmd.comp_mask) return -EINVAL; @@ -3259,8 +3273,7 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs, if (cmd.flow_attr.num_of_specs > IB_FLOW_SPEC_SUPPORT_LAYERS) return -EINVAL; - if (cmd.flow_attr.size > ucore->inlen || - cmd.flow_attr.size > + if (cmd.flow_attr.size > (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec))) return -EINVAL; @@ -3275,14 +3288,18 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs, return -ENOMEM; *kern_flow_attr = cmd.flow_attr; - err = ib_copy_from_udata(&kern_flow_attr->flow_specs, ucore, - cmd.flow_attr.size); + err = uverbs_request_next(&iter, &kern_flow_attr->flow_specs, + cmd.flow_attr.size); if (err) goto err_free_attr; } else { kern_flow_attr = &cmd.flow_attr; } + err = uverbs_request_finish(&iter); + if (err) + goto err_free_attr; + uobj = uobj_alloc(UVERBS_OBJECT_FLOW, attrs, &ib_dev); if (IS_ERR(uobj)) { err = PTR_ERR(uobj); From c3bea3d2dc5358e05541527283279102383b0231 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:43 +0200 Subject: [PATCH 10/12] RDMA/uverbs: Use the iterator for ib_uverbs_unmarshall_recv() This has a very complicated memory layout, with two flex arrays. Use the iterator API to make reading it clearer. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 103 ++++++++++++++++----------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a89b8442ca32..15b9db4463da 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -150,6 +150,17 @@ static int uverbs_request_next(struct uverbs_req_iter *iter, void *val, return 0; } +static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter, + size_t len) +{ + const void __user *res = iter->cur; + + if (iter->cur + len > iter->end) + return ERR_PTR(-ENOSPC); + iter->cur += len; + return res; +} + static int uverbs_request_finish(struct uverbs_req_iter *iter) { if (!ib_is_buffer_cleared(iter->cur, iter->end - iter->cur)) @@ -2073,16 +2084,23 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, int is_ud; int ret, ret2; size_t next_size; + const struct ib_sge __user *sgls; + const void __user *wqes; + struct uverbs_req_iter iter; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; - - if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count + - cmd.sge_count * sizeof (struct ib_uverbs_sge)) - return -EINVAL; - - if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr)) - return -EINVAL; + ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd)); + if (ret) + return ret; + wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count); + if (IS_ERR(wqes)) + return PTR_ERR(wqes); + sgls = uverbs_request_next_ptr( + &iter, cmd.sge_count * sizeof(struct ib_uverbs_sge)); + if (IS_ERR(sgls)) + return PTR_ERR(sgls); + ret = uverbs_request_finish(&iter); + if (ret) + return ret; user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL); if (!user_wr) @@ -2096,8 +2114,7 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, sg_ind = 0; last = NULL; for (i = 0; i < cmd.wr_count; ++i) { - if (copy_from_user(user_wr, - buf + sizeof cmd + i * cmd.wqe_size, + if (copy_from_user(user_wr, wqes + i * cmd.wqe_size, cmd.wqe_size)) { ret = -EFAULT; goto out_put; @@ -2205,11 +2222,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, if (next->num_sge) { next->sg_list = (void *) next + ALIGN(next_size, sizeof(struct ib_sge)); - if (copy_from_user(next->sg_list, - buf + sizeof cmd + - cmd.wr_count * cmd.wqe_size + - sg_ind * sizeof (struct ib_sge), - next->num_sge * sizeof (struct ib_sge))) { + if (copy_from_user(next->sg_list, sgls + sg_ind, + next->num_sge * + sizeof(struct ib_sge))) { ret = -EFAULT; goto out_put; } @@ -2248,25 +2263,32 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, return ret; } -static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf, - int in_len, - u32 wr_count, - u32 sge_count, - u32 wqe_size) +static struct ib_recv_wr * +ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count, + u32 wqe_size, u32 sge_count) { struct ib_uverbs_recv_wr *user_wr; struct ib_recv_wr *wr = NULL, *last, *next; int sg_ind; int i; int ret; - - if (in_len < wqe_size * wr_count + - sge_count * sizeof (struct ib_uverbs_sge)) - return ERR_PTR(-EINVAL); + const struct ib_sge __user *sgls; + const void __user *wqes; if (wqe_size < sizeof (struct ib_uverbs_recv_wr)) return ERR_PTR(-EINVAL); + wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count); + if (IS_ERR(wqes)) + return ERR_CAST(wqes); + sgls = uverbs_request_next_ptr( + iter, sge_count * sizeof(struct ib_uverbs_sge)); + if (IS_ERR(sgls)) + return ERR_CAST(sgls); + ret = uverbs_request_finish(iter); + if (ret) + return ERR_PTR(ret); + user_wr = kmalloc(wqe_size, GFP_KERNEL); if (!user_wr) return ERR_PTR(-ENOMEM); @@ -2274,7 +2296,7 @@ static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf, sg_ind = 0; last = NULL; for (i = 0; i < wr_count; ++i) { - if (copy_from_user(user_wr, buf + i * wqe_size, + if (copy_from_user(user_wr, wqes + i * wqe_size, wqe_size)) { ret = -EFAULT; goto err; @@ -2313,10 +2335,9 @@ static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf, if (next->num_sge) { next->sg_list = (void *) next + ALIGN(sizeof *next, sizeof (struct ib_sge)); - if (copy_from_user(next->sg_list, - buf + wr_count * wqe_size + - sg_ind * sizeof (struct ib_sge), - next->num_sge * sizeof (struct ib_sge))) { + if (copy_from_user(next->sg_list, sgls + sg_ind, + next->num_sge * + sizeof(struct ib_sge))) { ret = -EFAULT; goto err; } @@ -2349,13 +2370,14 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs, const struct ib_recv_wr *bad_wr; struct ib_qp *qp; int ret, ret2; + struct uverbs_req_iter iter; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd)); + if (ret) + return ret; - wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd, - in_len - sizeof cmd, cmd.wr_count, - cmd.sge_count, cmd.wqe_size); + wr = ib_uverbs_unmarshall_recv(&iter, cmd.wr_count, cmd.wqe_size, + cmd.sge_count); if (IS_ERR(wr)) return PTR_ERR(wr); @@ -2400,13 +2422,14 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs, const struct ib_recv_wr *bad_wr; struct ib_srq *srq; int ret, ret2; + struct uverbs_req_iter iter; - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; + ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd)); + if (ret) + return ret; - wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd, - in_len - sizeof cmd, cmd.wr_count, - cmd.sge_count, cmd.wqe_size); + wr = ib_uverbs_unmarshall_recv(&iter, cmd.wr_count, cmd.wqe_size, + cmd.sge_count); if (IS_ERR(wr)) return PTR_ERR(wr); From ece9ca97ccdc845c0c48e204e5a6d9149b7a24b3 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:44 +0200 Subject: [PATCH 11/12] RDMA/uverbs: Do not check the input length on create_cq/qp paths If the user did not provide a long enough command buffer then the missing bytes are forced to zero. There is no reason to check the length if a zero value is OK. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_cmd.c | 38 +++++++--------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 15b9db4463da..11e2175e0362 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1018,8 +1018,7 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, } static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_cq *cmd, - size_t cmd_sz) + struct ib_uverbs_ex_create_cq *cmd) { struct ib_ucq_object *obj; struct ib_uverbs_completion_event_file *ev_file = NULL; @@ -1053,9 +1052,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, attr.cqe = cmd->cqe; attr.comp_vector = cmd->comp_vector; - - if (cmd_sz > offsetof(typeof(*cmd), flags) + sizeof(cmd->flags)) - attr.flags = cmd->flags; + attr.flags = cmd->flags; cq = ib_dev->create_cq(ib_dev, &attr, obj->uobject.context, &attrs->driver_udata); @@ -1120,9 +1117,7 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, cmd_ex.comp_vector = cmd.comp_vector; cmd_ex.comp_channel = cmd.comp_channel; - obj = create_cq(attrs, &cmd_ex, - offsetof(typeof(cmd_ex), comp_channel) + - sizeof(cmd.comp_channel)); + obj = create_cq(attrs, &cmd_ex); return PTR_ERR_OR_ZERO(obj); } @@ -1143,7 +1138,7 @@ static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, if (cmd.reserved) return -EINVAL; - obj = create_cq(attrs, &cmd, min(ucore->inlen, sizeof(cmd))); + obj = create_cq(attrs, &cmd); return PTR_ERR_OR_ZERO(obj); } @@ -1309,7 +1304,7 @@ static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs, } static int create_qp(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_qp *cmd, size_t cmd_sz) + struct ib_uverbs_ex_create_qp *cmd) { struct ib_uqp_object *obj; struct ib_device *device; @@ -1319,7 +1314,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs, struct ib_cq *scq = NULL, *rcq = NULL; struct ib_srq *srq = NULL; struct ib_qp *qp; - char *buf; struct ib_qp_init_attr attr = {}; struct ib_uverbs_ex_create_qp_resp resp; int ret; @@ -1338,9 +1332,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, obj->uevent.uobject.user_handle = cmd->user_handle; mutex_init(&obj->mcast_lock); - if (cmd_sz >= offsetof(typeof(*cmd), rwq_ind_tbl_handle) + - sizeof(cmd->rwq_ind_tbl_handle) && - (cmd->comp_mask & IB_UVERBS_CREATE_QP_MASK_IND_TABLE)) { + if (cmd->comp_mask & IB_UVERBS_CREATE_QP_MASK_IND_TABLE) { ind_tbl = uobj_get_obj_read(rwq_ind_table, UVERBS_OBJECT_RWQ_IND_TBL, cmd->rwq_ind_tbl_handle, attrs); @@ -1438,10 +1430,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, INIT_LIST_HEAD(&obj->uevent.event_list); INIT_LIST_HEAD(&obj->mcast_list); - if (cmd_sz >= offsetof(typeof(*cmd), create_flags) + - sizeof(cmd->create_flags)) - attr.create_flags = cmd->create_flags; - + attr.create_flags = cmd->create_flags; if (attr.create_flags & ~(IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK | IB_QP_CREATE_CROSS_CHANNEL | IB_QP_CREATE_MANAGED_SEND | @@ -1463,14 +1452,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs, attr.source_qpn = cmd->source_qpn; } - buf = (void *)cmd + sizeof(*cmd); - if (cmd_sz > sizeof(*cmd)) - if (!(buf[0] == 0 && !memcmp(buf, buf + 1, - cmd_sz - sizeof(*cmd) - 1))) { - ret = -EINVAL; - goto err_put; - } - if (cmd->qp_type == IB_QPT_XRC_TGT) qp = ib_create_qp(pd, &attr); else @@ -1594,8 +1575,7 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, cmd_ex.qp_type = cmd.qp_type; cmd_ex.is_srq = cmd.is_srq; - return create_qp(attrs, &cmd_ex, - offsetof(typeof(cmd_ex), is_srq) + sizeof(cmd.is_srq)); + return create_qp(attrs, &cmd_ex); } static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, @@ -1614,7 +1594,7 @@ static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, if (cmd.reserved) return -EINVAL; - return create_qp(attrs, &cmd, min(ucore->inlen, sizeof(cmd))); + return create_qp(attrs, &cmd); } static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, From 974d6b4b2bc33c53334e086a40715b384f48f2e2 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 25 Nov 2018 20:58:45 +0200 Subject: [PATCH 12/12] RDMA/uverbs: Use only attrs for the write() handler signature All of the old arguments can be derived from the uverbs_attr_bundle structure, so get rid of the redundant arguments. Most of the prior work has been removing users of the arguments to allow this to be a simple patch. Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/rdma_core.h | 5 +- drivers/infiniband/core/uverbs_cmd.c | 150 ++++++++------------------ drivers/infiniband/core/uverbs_main.c | 4 +- drivers/infiniband/core/uverbs_uapi.c | 23 +--- include/rdma/uverbs_ioctl.h | 8 +- 5 files changed, 56 insertions(+), 134 deletions(-) diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h index b1bf1579fc26..bac484d6753a 100644 --- a/drivers/infiniband/core/rdma_core.h +++ b/drivers/infiniband/core/rdma_core.h @@ -137,10 +137,7 @@ struct uverbs_api_ioctl_method { }; struct uverbs_api_write_method { - int (*handler)(struct uverbs_attr_bundle *attrs, const char __user *buf, - int in_len, int out_len); - int (*handler_ex)(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore); + int (*handler)(struct uverbs_attr_bundle *attrs); u8 disabled:1; u8 is_ex:1; u8 has_udata:1; diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 11e2175e0362..4dab9f7e1f94 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -186,9 +186,7 @@ _ib_uverbs_lookup_comp_file(s32 fd, const struct uverbs_attr_bundle *attrs) #define ib_uverbs_lookup_comp_file(_fd, _ufile) \ _ib_uverbs_lookup_comp_file((_fd)*typecheck(s32, _fd), _ufile) -static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_file *file = attrs->ufile; struct ib_uverbs_get_context cmd; @@ -337,9 +335,7 @@ static void copy_query_dev_fields(struct ib_ucontext *ucontext, resp->phys_port_cnt = ib_dev->phys_port_cnt; } -static int ib_uverbs_query_device(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_query_device(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_query_device cmd; struct ib_uverbs_query_device_resp resp; @@ -381,8 +377,7 @@ static u32 make_port_cap_flags(const struct ib_port_attr *attr) return res; } -static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_query_port cmd; struct ib_uverbs_query_port_resp resp; @@ -440,8 +435,7 @@ static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); } -static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_alloc_pd cmd; struct ib_uverbs_alloc_pd_resp resp; @@ -489,8 +483,7 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_dealloc_pd(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_dealloc_pd(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_dealloc_pd cmd; int ret; @@ -587,8 +580,7 @@ static void xrcd_table_delete(struct ib_uverbs_device *dev, } } -static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_device *ibudev = attrs->ufile->device; struct ib_uverbs_open_xrcd cmd; @@ -700,8 +692,7 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_close_xrcd(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_close_xrcd(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_close_xrcd cmd; int ret; @@ -738,8 +729,7 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, return ret; } -static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_reg_mr cmd; struct ib_uverbs_reg_mr_resp resp; @@ -820,8 +810,7 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_rereg_mr cmd; struct ib_uverbs_rereg_mr_resp resp; @@ -899,8 +888,7 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_dereg_mr(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_dereg_mr(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_dereg_mr cmd; int ret; @@ -912,8 +900,7 @@ static int ib_uverbs_dereg_mr(struct uverbs_attr_bundle *attrs, return uobj_perform_destroy(UVERBS_OBJECT_MR, cmd.mr_handle, attrs); } -static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_alloc_mw cmd; struct ib_uverbs_alloc_mw_resp resp; @@ -970,8 +957,7 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_dealloc_mw(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_dealloc_mw(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_dealloc_mw cmd; int ret; @@ -983,9 +969,7 @@ static int ib_uverbs_dealloc_mw(struct uverbs_attr_bundle *attrs, return uobj_perform_destroy(UVERBS_OBJECT_MW, cmd.mw_handle, attrs); } -static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_comp_channel cmd; struct ib_uverbs_create_comp_channel_resp resp; @@ -1099,8 +1083,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, return ERR_PTR(ret); } -static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_cq cmd; struct ib_uverbs_ex_create_cq cmd_ex; @@ -1121,8 +1104,7 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, return PTR_ERR_OR_ZERO(obj); } -static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_create_cq cmd; struct ib_ucq_object *obj; @@ -1142,8 +1124,7 @@ static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs, return PTR_ERR_OR_ZERO(obj); } -static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_resize_cq cmd; struct ib_uverbs_resize_cq_resp resp = {}; @@ -1201,8 +1182,7 @@ static int copy_wc_to_user(struct ib_device *ib_dev, void __user *dest, return 0; } -static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_poll_cq cmd; struct ib_uverbs_poll_cq_resp resp; @@ -1252,9 +1232,7 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_req_notify_cq cmd; struct ib_cq *cq; @@ -1276,8 +1254,7 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs, return 0; } -static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_destroy_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_destroy_cq cmd; struct ib_uverbs_destroy_cq_resp resp; @@ -1549,8 +1526,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_qp cmd; struct ib_uverbs_ex_create_qp cmd_ex; @@ -1578,8 +1554,7 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, return create_qp(attrs, &cmd_ex); } -static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_create_qp cmd; int ret; @@ -1597,8 +1572,7 @@ static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs, return create_qp(attrs, &cmd); } -static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_open_qp cmd; struct ib_uverbs_create_qp_resp resp; @@ -1695,8 +1669,7 @@ static void copy_ah_attr_to_uverbs(struct ib_uverbs_qp_dest *uverb_attr, uverb_attr->port_num = rdma_ah_get_port_num(rdma_attr); } -static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_query_qp cmd; struct ib_uverbs_query_qp_resp resp; @@ -1968,8 +1941,7 @@ static int modify_qp(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_modify_qp cmd; int ret; @@ -1985,8 +1957,7 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs, return modify_qp(attrs, &cmd); } -static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_modify_qp cmd; struct ib_uverbs_ex_modify_qp_resp resp = { @@ -2015,8 +1986,7 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); } -static int ib_uverbs_destroy_qp(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_destroy_qp(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_destroy_qp cmd; struct ib_uverbs_destroy_qp_resp resp; @@ -2051,8 +2021,7 @@ static void *alloc_wr(size_t wr_size, __u32 num_sge) num_sge * sizeof (struct ib_sge), GFP_KERNEL); } -static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_post_send cmd; struct ib_uverbs_post_send_resp resp; @@ -2341,8 +2310,7 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count, return ERR_PTR(ret); } -static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_post_recv cmd; struct ib_uverbs_post_recv_resp resp; @@ -2392,9 +2360,7 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_post_srq_recv cmd; struct ib_uverbs_post_srq_recv_resp resp; @@ -2445,8 +2411,7 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_ah cmd; struct ib_uverbs_create_ah_resp resp; @@ -2524,8 +2489,7 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_destroy_ah(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_destroy_ah(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_destroy_ah cmd; int ret; @@ -2537,9 +2501,7 @@ static int ib_uverbs_destroy_ah(struct uverbs_attr_bundle *attrs, return uobj_perform_destroy(UVERBS_OBJECT_AH, cmd.ah_handle, attrs); } -static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_attach_mcast cmd; struct ib_qp *qp; @@ -2587,9 +2549,7 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_detach_mcast cmd; struct ib_uqp_object *obj; @@ -2950,8 +2910,7 @@ static int kern_spec_to_ib_spec(struct uverbs_attr_bundle *attrs, return kern_spec_to_ib_spec_filter(kern_spec, ib_spec); } -static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_create_wq cmd; struct ib_uverbs_ex_create_wq_resp resp = {}; @@ -3042,8 +3001,7 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs, return err; } -static int ib_uverbs_ex_destroy_wq(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_destroy_wq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_destroy_wq cmd; struct ib_uverbs_ex_destroy_wq_resp resp = {}; @@ -3071,8 +3029,7 @@ static int ib_uverbs_ex_destroy_wq(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); } -static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_modify_wq cmd; struct ib_wq *wq; @@ -3105,8 +3062,7 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_create_rwq_ind_table cmd; struct ib_uverbs_ex_create_rwq_ind_table_resp resp = {}; @@ -3220,8 +3176,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs, return err; } -static int ib_uverbs_ex_destroy_rwq_ind_table(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_destroy_rwq_ind_table(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_destroy_rwq_ind_table cmd; int ret; @@ -3237,8 +3192,7 @@ static int ib_uverbs_ex_destroy_rwq_ind_table(struct uverbs_attr_bundle *attrs, cmd.ind_tbl_handle, attrs); } -static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_flow cmd; struct ib_uverbs_create_flow_resp resp; @@ -3403,8 +3357,7 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs, return err; } -static int ib_uverbs_ex_destroy_flow(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_destroy_flow(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_destroy_flow cmd; int ret; @@ -3553,8 +3506,7 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_create_srq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_create_srq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_srq cmd; struct ib_uverbs_create_xsrq xcmd; @@ -3576,9 +3528,7 @@ static int ib_uverbs_create_srq(struct uverbs_attr_bundle *attrs, return __uverbs_create_xsrq(attrs, &xcmd, &attrs->driver_udata); } -static int ib_uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_create_xsrq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_xsrq cmd; int ret; @@ -3590,8 +3540,7 @@ static int ib_uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, return __uverbs_create_xsrq(attrs, &cmd, &attrs->driver_udata); } -static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_modify_srq cmd; struct ib_srq *srq; @@ -3617,8 +3566,7 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs, return ret; } -static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) +static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_query_srq cmd; struct ib_uverbs_query_srq_resp resp; @@ -3650,9 +3598,7 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); } -static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len) +static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_destroy_srq cmd; struct ib_uverbs_destroy_srq_resp resp; @@ -3677,8 +3623,7 @@ static int ib_uverbs_destroy_srq(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); } -static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_query_device_resp resp = {}; struct ib_uverbs_ex_query_device cmd; @@ -3743,8 +3688,7 @@ static int ib_uverbs_ex_query_device(struct uverbs_attr_bundle *attrs, return uverbs_response(attrs, &resp, sizeof(resp)); } -static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_modify_cq cmd; struct ib_cq *cq; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 762a6acbff80..96a5f89bbb75 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -739,8 +739,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ib_uverbs_init_udata_buf_or_null( &bundle.ucore, buf, u64_to_user_ptr(response), in_len, out_len); - - ret = method_elm->handler(&bundle, buf, in_len, out_len); } else { buf += sizeof(ex_hdr); @@ -754,9 +752,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ex_hdr.provider_in_words * 8, ex_hdr.provider_out_words * 8); - ret = method_elm->handler_ex(&bundle, &bundle.ucore); } + ret = method_elm->handler(&bundle); out_unlock: srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); return (ret) ? : count; diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c index b3d5f36b0462..19ae4b19b2ef 100644 --- a/drivers/infiniband/core/uverbs_uapi.c +++ b/drivers/infiniband/core/uverbs_uapi.c @@ -8,14 +8,7 @@ #include "rdma_core.h" #include "uverbs.h" -static int ib_uverbs_notsupp(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, int out_len) -{ - return -EOPNOTSUPP; -} - -static int ib_uverbs_ex_notsupp(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore) +static int ib_uverbs_notsupp(struct uverbs_attr_bundle *attrs) { return -EOPNOTSUPP; } @@ -79,22 +72,17 @@ static int uapi_create_write(struct uverbs_api *uapi, if (IS_ERR(method_elm)) return PTR_ERR(method_elm); - if (WARN_ON(exists && (def->write.is_ex != method_elm->is_ex || - method_elm->handler_ex || method_elm->handler))) + if (WARN_ON(exists && (def->write.is_ex != method_elm->is_ex))) return -EINVAL; method_elm->is_ex = def->write.is_ex; - if (def->write.is_ex) { - method_elm->handler_ex = def->func_write_ex; - + method_elm->handler = def->func_write; + if (def->write.is_ex) method_elm->disabled = !(ibdev->uverbs_ex_cmd_mask & BIT_ULL(def->write.command_num)); - } else { - method_elm->handler = def->func_write; - + else method_elm->disabled = !(ibdev->uverbs_cmd_mask & BIT_ULL(def->write.command_num)); - } if (!def->write.is_ex && def->func_write) { method_elm->has_udata = def->write.has_udata; @@ -449,7 +437,6 @@ static int uapi_finalize(struct uverbs_api *uapi) } uapi->notsupp_method.handler = ib_uverbs_notsupp; - uapi->notsupp_method.handler_ex = ib_uverbs_ex_notsupp; uapi->num_write = max_write + 1; uapi->num_write_ex = max_write_ex + 1; data = kmalloc_array(uapi->num_write + uapi->num_write_ex, diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 9486a525afc1..7f4ace93e502 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h @@ -373,11 +373,7 @@ struct uapi_definition { union { bool (*func_is_supported)(struct ib_device *device); - int (*func_write)(struct uverbs_attr_bundle *attrs, - const char __user *buf, int in_len, - int out_len); - int (*func_write_ex)(struct uverbs_attr_bundle *attrs, - struct ib_udata *ucore); + int (*func_write)(struct uverbs_attr_bundle *attrs); const struct uapi_definition *chain; const struct uverbs_object_def *chain_obj_tree; size_t needs_fn_offset; @@ -409,7 +405,7 @@ struct uapi_definition { .kind = UAPI_DEF_WRITE, \ .scope = UAPI_SCOPE_OBJECT, \ .write = { .is_ex = 1, .command_num = _command_num }, \ - .func_write_ex = _func, \ + .func_write = _func, \ _cmd_desc, \ }, \ ##__VA_ARGS__