mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
RDMA/core: Move the _ib_copy_validate_udata* functions to ib_core_uverbs
It was incorrect to place them in uverbs_ioctl because that makes every
driver depends on ib_uverbs.ko, which is undesired. ib_core_uverbs.c is
for functions used by alot of drivers that are linked into ib_core
instead.
Fixes: 1de9287ece ("RDMA: Add ib_copy_validate_udata_in()")
Link: https://patch.msgid.link/r/1-v1-045258567bd6+9fe-ib_uverbs_support_ko_jgg@nvidia.com
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
0ce1bc9e46
commit
01f99f8c4a
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/dma-resv.h>
|
||||
#include "uverbs.h"
|
||||
#include "core_priv.h"
|
||||
#include "rdma_core.h"
|
||||
|
||||
MODULE_IMPORT_NS("DMA_BUF");
|
||||
|
||||
|
|
@ -416,3 +417,91 @@ struct ib_device *rdma_udata_to_dev(struct ib_udata *udata)
|
|||
}
|
||||
EXPORT_SYMBOL(rdma_udata_to_dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int _ib_copy_validate_udata_cm_fail(struct ib_udata *udata, u64 req_cm,
|
||||
u64 valid_cm)
|
||||
{
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver input udata has unsupported comp_mask %llx & ~%llx = %llx for ioctl %ps called by %pSR\n",
|
||||
req_cm, valid_cm, req_cm & ~valid_cm,
|
||||
uverbs_get_handler_fn(udata), __builtin_return_address(0));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
EXPORT_SYMBOL(_ib_copy_validate_udata_cm_fail);
|
||||
|
||||
int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len)
|
||||
{
|
||||
size_t copy_len;
|
||||
|
||||
/* 0 length copy_len is a NOP for copy_to_user() and doesn't fail. */
|
||||
copy_len = min(len, udata->outlen);
|
||||
if (copy_to_user(udata->outbuf, src, copy_len))
|
||||
goto err_fault;
|
||||
if (copy_len < udata->outlen) {
|
||||
if (clear_user(udata->outbuf + copy_len,
|
||||
udata->outlen - copy_len))
|
||||
goto err_fault;
|
||||
}
|
||||
return 0;
|
||||
err_fault:
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver out udata has EFAULT (%zu into %zu) for ioctl %ps called by %pSR\n",
|
||||
len, udata->outlen, uverbs_get_handler_fn(udata),
|
||||
__builtin_return_address(0));
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL(_ib_respond_udata);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -229,6 +229,41 @@ int uverbs_dealloc_mw(struct ib_mw *mw);
|
|||
void ib_uverbs_detach_umcast(struct ib_qp *qp,
|
||||
struct ib_uqp_object *uobj);
|
||||
|
||||
struct bundle_alloc_head {
|
||||
struct_group_tagged(bundle_alloc_head_hdr, hdr,
|
||||
struct bundle_alloc_head *next;
|
||||
);
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct bundle_priv {
|
||||
/* Must be first */
|
||||
struct bundle_alloc_head_hdr alloc_head;
|
||||
struct bundle_alloc_head *allocated_mem;
|
||||
size_t internal_avail;
|
||||
size_t internal_used;
|
||||
|
||||
struct radix_tree_root *radix;
|
||||
const struct uverbs_api_ioctl_method *method_elm;
|
||||
void __rcu **radix_slots;
|
||||
unsigned long radix_slots_len;
|
||||
u32 method_key;
|
||||
|
||||
struct ib_uverbs_attr __user *user_attrs;
|
||||
struct ib_uverbs_attr *uattrs;
|
||||
|
||||
DECLARE_BITMAP(uobj_finalize, UVERBS_API_ATTR_BKEY_LEN);
|
||||
DECLARE_BITMAP(spec_finalize, UVERBS_API_ATTR_BKEY_LEN);
|
||||
DECLARE_BITMAP(uobj_hw_obj_valid, UVERBS_API_ATTR_BKEY_LEN);
|
||||
|
||||
/*
|
||||
* Must be last. bundle ends in a flex array which overlaps
|
||||
* internal_buffer.
|
||||
*/
|
||||
struct uverbs_attr_bundle_hdr bundle;
|
||||
u64 internal_buffer[32];
|
||||
};
|
||||
|
||||
long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
|
||||
struct ib_uverbs_flow_spec {
|
||||
|
|
|
|||
|
|
@ -35,54 +35,6 @@
|
|||
#include "rdma_core.h"
|
||||
#include "uverbs.h"
|
||||
|
||||
struct bundle_alloc_head {
|
||||
struct_group_tagged(bundle_alloc_head_hdr, hdr,
|
||||
struct bundle_alloc_head *next;
|
||||
);
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct bundle_priv {
|
||||
/* Must be first */
|
||||
struct bundle_alloc_head_hdr alloc_head;
|
||||
struct bundle_alloc_head *allocated_mem;
|
||||
size_t internal_avail;
|
||||
size_t internal_used;
|
||||
|
||||
struct radix_tree_root *radix;
|
||||
const struct uverbs_api_ioctl_method *method_elm;
|
||||
void __rcu **radix_slots;
|
||||
unsigned long radix_slots_len;
|
||||
u32 method_key;
|
||||
|
||||
struct ib_uverbs_attr __user *user_attrs;
|
||||
struct ib_uverbs_attr *uattrs;
|
||||
|
||||
DECLARE_BITMAP(uobj_finalize, UVERBS_API_ATTR_BKEY_LEN);
|
||||
DECLARE_BITMAP(spec_finalize, UVERBS_API_ATTR_BKEY_LEN);
|
||||
DECLARE_BITMAP(uobj_hw_obj_valid, UVERBS_API_ATTR_BKEY_LEN);
|
||||
|
||||
/*
|
||||
* Must be last. bundle ends in a flex array which overlaps
|
||||
* internal_buffer.
|
||||
*/
|
||||
struct uverbs_attr_bundle_hdr bundle;
|
||||
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
|
||||
|
|
@ -860,77 +812,3 @@ 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);
|
||||
|
||||
int _ib_copy_validate_udata_cm_fail(struct ib_udata *udata, u64 req_cm,
|
||||
u64 valid_cm)
|
||||
{
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver input udata has unsupported comp_mask %llx & ~%llx = %llx for ioctl %ps called by %pSR\n",
|
||||
req_cm, valid_cm, req_cm & ~valid_cm,
|
||||
uverbs_get_handler_fn(udata), __builtin_return_address(0));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
EXPORT_SYMBOL(_ib_copy_validate_udata_cm_fail);
|
||||
|
||||
int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len)
|
||||
{
|
||||
size_t copy_len;
|
||||
|
||||
/* 0 length copy_len is a NOP for copy_to_user() and doesn't fail. */
|
||||
copy_len = min(len, udata->outlen);
|
||||
if (copy_to_user(udata->outbuf, src, copy_len))
|
||||
goto err_fault;
|
||||
if (copy_len < udata->outlen) {
|
||||
if (clear_user(udata->outbuf + copy_len,
|
||||
udata->outlen - copy_len))
|
||||
goto err_fault;
|
||||
}
|
||||
return 0;
|
||||
err_fault:
|
||||
ibdev_dbg(
|
||||
rdma_udata_to_dev(udata),
|
||||
"System call driver out udata has EFAULT (%zu into %zu) for ioctl %ps called by %pSR\n",
|
||||
len, udata->outlen, uverbs_get_handler_fn(udata),
|
||||
__builtin_return_address(0));
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL(_ib_respond_udata);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user