Commit 61d69528 authored by Doug Ledford's avatar Doug Ledford

Merge branch 'write-handler-consistent-flow' into for-next

Make all of the write() handlers use a consistent flow

From Jason,

This series unifies all the write handlers to use a flow that is very
similar to the ioctl handler flow, including having the same basic
assumptions about extensible buffer handling and the same handler
function call signature.

Along the way this consolidates all the copy_to/from_user into a small
set of safe buffer accessor functions tailored to the usage here. These
accessors use the new dispatcher-controlled calling convention for ucore
data, and support a placement of the response that does not rely on the
cmd.response value.

Overall this brings in in strong bounds checking to all the write()
handlers and consistent enforcement of the zero-fill/zero-check
methodology for buffer extension.

The end result is a significant complexity reduction for all of the
handlers and creates a high degree of uniformity between the write,
write_ex, and ioctl handlers and dispatch flow.

Thanks

Jason Gunthorpe (12):
  RDMA/uverbs: Remove out_len checks that are now done by the core
  RDMA/uverbs: Use uverbs_attr_bundle to pass ucore for write/write_ex
  RDMA/uverbs: Get rid of the 'callback' scheme in the compat path
  RDMA/uverbs: Use uverbs_response() for remaining response copying
  RDMA/uverbs: Use uverbs_request() for request copying
  RDMA/uverbs: Use uverbs_request() and core for write_ex handlers
  RDMA/uverbs: Fill in the response for IB_USER_VERBS_EX_CMD_MODIFY_QP
  RDMA/uverbs: Simplify ib_uverbs_ex_query_device
  RDMA/uverbs: Add a simple iterator interface for reading the command
  RDMA/uverbs: Use the iterator for ib_uverbs_unmarshall_recv()
  RDMA/uverbs: Do not check the input length on create_cq/qp paths
  RDMA/uverbs: Use only attrs for the write() handler signature

 drivers/infiniband/core/rdma_core.h   |    5 +-
 drivers/infiniband/core/uverbs_cmd.c  | 1165 ++++++++++---------------
 drivers/infiniband/core/uverbs_main.c |   23 +-
 drivers/infiniband/core/uverbs_uapi.c |   23 +-
 include/rdma/uverbs_ioctl.h           |    9 +-
 5 files changed, 479 insertions(+), 746 deletions(-)
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parents 34f4c955 974d6b4b
......@@ -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;
......
This diff is collapsed.
......@@ -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,25 +736,25 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
bundle.driver_udata.outbuf = NULL;
}
ret = method_elm->handler(&bundle, buf, in_len, out_len);
ib_uverbs_init_udata_buf_or_null(
&bundle.ucore, buf, u64_to_user_ptr(response),
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(&bundle);
out_unlock:
srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
return (ret) ? : count;
......
......@@ -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,
......
......@@ -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__
......@@ -647,6 +643,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[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment