mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 00:28:54 +02:00
RDMA: Add ib_copy_validate_udata_in()
Add a new function to consolidate the required compatibility pattern for driver data of checking against a minimum size, and checking for unknown trailing bytes to be zero into a function. This new function uses the faster copy_struct_from_user() instead of trying to directly check for zero. Incorporate the common ibdev_dbg() logging directly into the error paths of the helper. Link: https://patch.msgid.link/r/3-v3-bd56dd443069+49-bnxt_re_uapi_jgg@nvidia.com Tested-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com> Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
b51caeb24a
commit
1de9287ece
|
|
@ -151,6 +151,9 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
|
|||
unsigned int num_attrs);
|
||||
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);
|
||||
|
||||
typedef int (*uverbs_api_ioctl_handler_fn)(struct uverbs_attr_bundle *attrs);
|
||||
uverbs_api_ioctl_handler_fn uverbs_get_handler_fn(struct ib_udata *udata);
|
||||
|
||||
extern const struct uapi_definition uverbs_def_obj_async_fd[];
|
||||
extern const struct uapi_definition uverbs_def_obj_counters[];
|
||||
extern const struct uapi_definition uverbs_def_obj_cq[];
|
||||
|
|
|
|||
|
|
@ -70,6 +70,19 @@ struct bundle_priv {
|
|||
u64 internal_buffer[32];
|
||||
};
|
||||
|
||||
uverbs_api_ioctl_handler_fn uverbs_get_handler_fn(struct ib_udata *udata)
|
||||
{
|
||||
struct uverbs_attr_bundle *bundle =
|
||||
rdma_udata_to_uverbs_attr_bundle(udata);
|
||||
struct bundle_priv *pbundle =
|
||||
container_of(&bundle->hdr, struct bundle_priv, bundle);
|
||||
|
||||
lockdep_assert_held(&bundle->ufile->device->disassociate_srcu);
|
||||
|
||||
return srcu_dereference(pbundle->method_elm->handler,
|
||||
&bundle->ufile->device->disassociate_srcu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Each method has an absolute minimum amount of memory it needs to allocate,
|
||||
* precompute that amount and determine if the onstack memory can be used or
|
||||
|
|
@ -847,3 +860,41 @@ void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *bundle,
|
|||
pbundle->uobj_hw_obj_valid);
|
||||
}
|
||||
EXPORT_SYMBOL(uverbs_finalize_uobj_create);
|
||||
|
||||
int _ib_copy_validate_udata_in(struct ib_udata *udata, void *req,
|
||||
size_t kernel_size, size_t minimum_size)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (udata->inlen < minimum_size) {
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver input udata too small (%zu < %zu) for ioctl %ps called by %pSR\n",
|
||||
udata->inlen, minimum_size,
|
||||
uverbs_get_handler_fn(udata),
|
||||
__builtin_return_address(0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = copy_struct_from_user(req, kernel_size, udata->inbuf,
|
||||
udata->inlen);
|
||||
if (err) {
|
||||
if (err == -E2BIG) {
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver input udata not zero from %zu -> %zu for ioctl %ps called by %pSR\n",
|
||||
minimum_size, udata->inlen,
|
||||
uverbs_get_handler_fn(udata),
|
||||
__builtin_return_address(0));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver input udata EFAULT for ioctl %ps called by %pSR\n",
|
||||
uverbs_get_handler_fn(udata),
|
||||
__builtin_return_address(0));
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(_ib_copy_validate_udata_in);
|
||||
|
|
|
|||
|
|
@ -897,6 +897,9 @@ int _uverbs_get_const_unsigned(u64 *to,
|
|||
size_t idx, u64 upper_bound, u64 *def_val);
|
||||
int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
|
||||
size_t idx, const void *from, size_t size);
|
||||
|
||||
int _ib_copy_validate_udata_in(struct ib_udata *udata, void *req,
|
||||
size_t kernel_size, size_t minimum_size);
|
||||
#else
|
||||
static inline int
|
||||
uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
|
||||
|
|
@ -953,6 +956,14 @@ _uverbs_get_const_unsigned(u64 *to,
|
|||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int _ib_copy_validate_udata_in(struct ib_udata *udata, void *req,
|
||||
size_t kernel_size,
|
||||
size_t minimum_size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define uverbs_get_const_signed(_to, _attrs_bundle, _idx) \
|
||||
|
|
@ -1018,4 +1029,19 @@ uverbs_get_raw_fd(int *to, const struct uverbs_attr_bundle *attrs_bundle,
|
|||
return uverbs_get_const_signed(to, attrs_bundle, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_copy_validate_udata_in - Copy and validate that the request structure is
|
||||
* compatible with this kernel
|
||||
* @_udata: The system calls ib_udata struct
|
||||
* @_req: The name of an on-stack structure that holds the driver data
|
||||
* @_end_member: The member in the struct that is the original end of struct
|
||||
* from the first kernel to introduce it.
|
||||
*
|
||||
* Check that the udata input request struct is properly formed for this kernel.
|
||||
* Then copy it into req
|
||||
*/
|
||||
#define ib_copy_validate_udata_in(_udata, _req, _end_member) \
|
||||
_ib_copy_validate_udata_in(_udata, &(_req), sizeof(_req), \
|
||||
offsetofend(typeof(_req), _end_member))
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user