aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/rdma_core.c22
-rw-r--r--drivers/infiniband/core/rdma_core.h2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c8
-rw-r--r--drivers/infiniband/core/uverbs_ioctl.c16
-rw-r--r--include/rdma/uverbs_std_types.h38
-rw-r--r--include/rdma/uverbs_types.h4
-rw-r--r--include/uapi/rdma/rdma_user_ioctl_cmds.h7
7 files changed, 59 insertions, 38 deletions
diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index aed7cc2a9e86..c63583dbc6b9 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -133,7 +133,7 @@ static int uverbs_try_lock_object(struct ib_uobject *uobj, bool exclusive)
* returns success_res on success (negative errno on failure). For use by
* callers that do not need the uobj.
*/
-int __uobj_perform_destroy(const struct uverbs_obj_type *type, int id,
+int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id,
struct ib_uverbs_file *ufile, int success_res)
{
struct ib_uobject *uobj;
@@ -212,13 +212,17 @@ static void uverbs_idr_remove_uobj(struct ib_uobject *uobj)
/* Returns the ib_uobject or an error. The caller should check for IS_ERR. */
static struct ib_uobject *
lookup_get_idr_uobject(const struct uverbs_obj_type *type,
- struct ib_uverbs_file *ufile, int id, bool exclusive)
+ struct ib_uverbs_file *ufile, s64 id, bool exclusive)
{
struct ib_uobject *uobj;
+ unsigned long idrno = id;
+
+ if (id < 0 || id > ULONG_MAX)
+ return ERR_PTR(-EINVAL);
rcu_read_lock();
/* object won't be released as we're protected in rcu */
- uobj = idr_find(&ufile->idr, id);
+ uobj = idr_find(&ufile->idr, idrno);
if (!uobj) {
uobj = ERR_PTR(-ENOENT);
goto free;
@@ -240,17 +244,21 @@ free:
static struct ib_uobject *lookup_get_fd_uobject(const struct uverbs_obj_type *type,
struct ib_uverbs_file *ufile,
- int id, bool exclusive)
+ s64 id, bool exclusive)
{
struct file *f;
struct ib_uobject *uobject;
+ int fdno = id;
const struct uverbs_obj_fd_type *fd_type =
container_of(type, struct uverbs_obj_fd_type, type);
+ if (fdno != id)
+ return ERR_PTR(-EINVAL);
+
if (exclusive)
return ERR_PTR(-EOPNOTSUPP);
- f = fget(id);
+ f = fget(fdno);
if (!f)
return ERR_PTR(-EBADF);
@@ -270,7 +278,7 @@ static struct ib_uobject *lookup_get_fd_uobject(const struct uverbs_obj_type *ty
}
struct ib_uobject *rdma_lookup_get_uobject(const struct uverbs_obj_type *type,
- struct ib_uverbs_file *ufile, int id,
+ struct ib_uverbs_file *ufile, s64 id,
bool exclusive)
{
struct ib_uobject *uobj;
@@ -725,7 +733,7 @@ EXPORT_SYMBOL(uverbs_fd_class);
struct ib_uobject *
uverbs_get_uobject_from_file(const struct uverbs_obj_type *type_attrs,
struct ib_uverbs_file *ufile,
- enum uverbs_obj_access access, int id)
+ enum uverbs_obj_access access, s64 id)
{
switch (access) {
case UVERBS_ACCESS_READ:
diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
index 1bba60e960c1..db2339330f6f 100644
--- a/drivers/infiniband/core/rdma_core.h
+++ b/drivers/infiniband/core/rdma_core.h
@@ -86,7 +86,7 @@ void uverbs_close_fd(struct file *f);
struct ib_uobject *
uverbs_get_uobject_from_file(const struct uverbs_obj_type *type_attrs,
struct ib_uverbs_file *ufile,
- enum uverbs_obj_access access, int id);
+ enum uverbs_obj_access access, s64 id);
/*
* Note that certain finalize stages could return a status:
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 987ee38ab4b3..409fd46a2a99 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -48,10 +48,10 @@
#include "core_priv.h"
static struct ib_uverbs_completion_event_file *
-ib_uverbs_lookup_comp_file(int fd, struct ib_uverbs_file *ufile)
+_ib_uverbs_lookup_comp_file(s32 fd, struct ib_uverbs_file *ufile)
{
- struct ib_uobject *uobj = uobj_get_read(UVERBS_OBJECT_COMP_CHANNEL,
- fd, ufile);
+ struct ib_uobject *uobj = ufd_get_read(UVERBS_OBJECT_COMP_CHANNEL,
+ fd, ufile);
if (IS_ERR(uobj))
return (void *)uobj;
@@ -62,6 +62,8 @@ ib_uverbs_lookup_comp_file(int fd, struct ib_uverbs_file *ufile)
return container_of(uobj, struct ib_uverbs_completion_event_file,
uobj);
}
+#define ib_uverbs_lookup_comp_file(_fd, _ufile) \
+ _ib_uverbs_lookup_comp_file((_fd)*typecheck(s32, _fd), _ufile)
ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
struct ib_device *ib_dev,
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index d3bf82cfaa2b..26ddc5cadcdb 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -136,15 +136,11 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
break;
case UVERBS_ATTR_TYPE_IDR:
- if (uattr->data >> 32)
- return -EINVAL;
- /* fall through */
case UVERBS_ATTR_TYPE_FD:
if (uattr->attr_data.reserved)
return -EINVAL;
- if (uattr->len != 0 || !ufile->ucontext ||
- uattr->data > INT_MAX)
+ if (uattr->len != 0 || !ufile->ucontext)
return -EINVAL;
o_attr = &e->obj_attr;
@@ -152,17 +148,23 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
if (!object)
return -EINVAL;
+ /*
+ * The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and
+ * s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64
+ * here without caring about truncation as we know that the
+ * IDR implementation today rejects negative IDs
+ */
o_attr->uobject = uverbs_get_uobject_from_file(
object->type_attrs,
ufile,
spec->u.obj.access,
- (int)uattr->data);
+ uattr->data_s64);
if (IS_ERR(o_attr->uobject))
return PTR_ERR(o_attr->uobject);
if (spec->u.obj.access == UVERBS_ACCESS_NEW) {
- u64 id = o_attr->uobject->id;
+ s64 id = o_attr->uobject->id;
/* Copy the allocated id to the user-space */
if (put_user(id, &e->uattr->data)) {
diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h
index 3e3f108f0912..4f32eab8b7a4 100644
--- a/include/rdma/uverbs_std_types.h
+++ b/include/rdma/uverbs_std_types.h
@@ -46,39 +46,43 @@ static inline const struct uverbs_object_tree_def *uverbs_default_get_objects(vo
}
#endif
-static inline struct ib_uobject *__uobj_get(const struct uverbs_obj_type *type,
- bool write,
- struct ib_uverbs_file *ufile,
- int id)
-{
- return rdma_lookup_get_uobject(type, ufile, id, write);
-}
+/* Returns _id, or causes a compile error if _id is not a u32.
+ *
+ * The uobj APIs should only be used with the write based uAPI to access
+ * object IDs. The write API must use a u32 for the object handle, which is
+ * checked by this macro.
+ */
+#define _uobj_check_id(_id) ((_id) * typecheck(u32, _id))
#define uobj_get_type(_object) UVERBS_OBJECT(_object).type_attrs
#define uobj_get_read(_type, _id, _ufile) \
- __uobj_get(uobj_get_type(_type), false, _ufile, _id)
+ rdma_lookup_get_uobject(uobj_get_type(_type), _ufile, \
+ _uobj_check_id(_id), false)
-static inline void *_uobj_get_obj_read(const struct uverbs_obj_type *type,
- int id, struct ib_uverbs_file *ufile)
-{
- struct ib_uobject *uobj = __uobj_get(type, false, ufile, id);
+#define ufd_get_read(_type, _fdnum, _ufile) \
+ rdma_lookup_get_uobject(uobj_get_type(_type), _ufile, \
+ (_fdnum)*typecheck(s32, _fdnum), false)
+static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
+{
if (IS_ERR(uobj))
return NULL;
return uobj->object;
}
#define uobj_get_obj_read(_object, _type, _id, _ufile) \
- ((struct ib_##_object *)_uobj_get_obj_read(uobj_get_type(_type), _id, \
- _ufile))
+ ((struct ib_##_object *)_uobj_get_obj_read( \
+ uobj_get_read(_type, _id, _ufile)))
#define uobj_get_write(_type, _id, _ufile) \
- __uobj_get(uobj_get_type(_type), true, _ufile, _id)
+ rdma_lookup_get_uobject(uobj_get_type(_type), _ufile, \
+ _uobj_check_id(_id), true)
-int __uobj_perform_destroy(const struct uverbs_obj_type *type, int id,
+int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id,
struct ib_uverbs_file *ufile, int success_res);
#define uobj_perform_destroy(_type, _id, _ufile, _success_res) \
- __uobj_perform_destroy(uobj_get_type(_type), _id, _ufile, _success_res)
+ __uobj_perform_destroy(uobj_get_type(_type), _uobj_check_id(_id), \
+ _ufile, _success_res)
static inline void uobj_put_read(struct ib_uobject *uobj)
{
diff --git a/include/rdma/uverbs_types.h b/include/rdma/uverbs_types.h
index e2fc9db466d3..2f50cc6def3c 100644
--- a/include/rdma/uverbs_types.h
+++ b/include/rdma/uverbs_types.h
@@ -77,7 +77,7 @@ struct uverbs_obj_type_class {
void (*alloc_abort)(struct ib_uobject *uobj);
struct ib_uobject *(*lookup_get)(const struct uverbs_obj_type *type,
- struct ib_uverbs_file *ufile, int id,
+ struct ib_uverbs_file *ufile, s64 id,
bool exclusive);
void (*lookup_put)(struct ib_uobject *uobj, bool exclusive);
/*
@@ -121,7 +121,7 @@ struct uverbs_obj_idr_type {
struct ib_uobject *rdma_lookup_get_uobject(const struct uverbs_obj_type *type,
struct ib_uverbs_file *ufile,
- int id, bool exclusive);
+ s64 id, bool exclusive);
void rdma_lookup_put_uobject(struct ib_uobject *uobj, bool exclusive);
struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_obj_type *type,
struct ib_uverbs_file *ufile);
diff --git a/include/uapi/rdma/rdma_user_ioctl_cmds.h b/include/uapi/rdma/rdma_user_ioctl_cmds.h
index 1da5a1e1f3a8..24800c6c1f32 100644
--- a/include/uapi/rdma/rdma_user_ioctl_cmds.h
+++ b/include/uapi/rdma/rdma_user_ioctl_cmds.h
@@ -62,7 +62,12 @@ struct ib_uverbs_attr {
} enum_data;
__u16 reserved;
} attr_data;
- __aligned_u64 data; /* ptr to command, inline data or idr/fd */
+ union {
+ /* Used by PTR_IN/OUT, ENUM_IN and IDR */
+ __aligned_u64 data;
+ /* Used by FD_IN and FD_OUT */
+ __s64 data_s64;
+ };
};
struct ib_uverbs_ioctl_hdr {