Commit 2f36028c authored by Jason Gunthorpe's avatar Jason Gunthorpe

IB/uverbs: Use u64_to_user_ptr() not a union

The union approach will get the endianness wrong sometimes if the kernel's
pointer size is 32 bits resulting in EFAULTs when trying to copy to/from
user.
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Reviewed-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 6c976c30
...@@ -238,14 +238,14 @@ static void create_udata(struct uverbs_attr_bundle *ctx, ...@@ -238,14 +238,14 @@ static void create_udata(struct uverbs_attr_bundle *ctx,
if (uverbs_attr_ptr_is_inline(uhw_in)) if (uverbs_attr_ptr_is_inline(uhw_in))
udata->inbuf = &uhw_in->uattr->data; udata->inbuf = &uhw_in->uattr->data;
else else
udata->inbuf = uhw_in->ptr_attr.ptr; udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data);
} else { } else {
udata->inbuf = NULL; udata->inbuf = NULL;
udata->inlen = 0; udata->inlen = 0;
} }
if (!IS_ERR(uhw_out)) { if (!IS_ERR(uhw_out)) {
udata->outbuf = uhw_out->ptr_attr.ptr; udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data);
udata->outlen = uhw_out->ptr_attr.len; udata->outlen = uhw_out->ptr_attr.len;
} else { } else {
udata->outbuf = NULL; udata->outbuf = NULL;
......
...@@ -276,10 +276,7 @@ struct uverbs_object_tree_def { ...@@ -276,10 +276,7 @@ struct uverbs_object_tree_def {
*/ */
struct uverbs_ptr_attr { struct uverbs_ptr_attr {
union {
u64 data; u64 data;
void __user *ptr;
};
u16 len; u16 len;
/* Combination of bits from enum UVERBS_ATTR_F_XXXX */ /* Combination of bits from enum UVERBS_ATTR_F_XXXX */
u16 flags; u16 flags;
...@@ -361,7 +358,7 @@ static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, ...@@ -361,7 +358,7 @@ static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
return PTR_ERR(attr); return PTR_ERR(attr);
min_size = min_t(size_t, attr->ptr_attr.len, size); min_size = min_t(size_t, attr->ptr_attr.len, size);
if (copy_to_user(attr->ptr_attr.ptr, from, min_size)) if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
return -EFAULT; return -EFAULT;
flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT; flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
...@@ -396,7 +393,8 @@ static inline int _uverbs_copy_from(void *to, ...@@ -396,7 +393,8 @@ static inline int _uverbs_copy_from(void *to,
if (uverbs_attr_ptr_is_inline(attr)) if (uverbs_attr_ptr_is_inline(attr))
memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len); memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
else if (copy_from_user(to, attr->ptr_attr.ptr, attr->ptr_attr.len)) else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
attr->ptr_attr.len))
return -EFAULT; return -EFAULT;
return 0; return 0;
......
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