Skip to content

Commit 01f99f8

Browse files
committed
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: 1de9287 ("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>
1 parent 0ce1bc9 commit 01f99f8

3 files changed

Lines changed: 124 additions & 122 deletions

File tree

drivers/infiniband/core/ib_core_uverbs.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/dma-resv.h>
1010
#include "uverbs.h"
1111
#include "core_priv.h"
12+
#include "rdma_core.h"
1213

1314
MODULE_IMPORT_NS("DMA_BUF");
1415

@@ -416,3 +417,91 @@ struct ib_device *rdma_udata_to_dev(struct ib_udata *udata)
416417
}
417418
EXPORT_SYMBOL(rdma_udata_to_dev);
418419

420+
#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
421+
uverbs_api_ioctl_handler_fn uverbs_get_handler_fn(struct ib_udata *udata)
422+
{
423+
struct uverbs_attr_bundle *bundle =
424+
rdma_udata_to_uverbs_attr_bundle(udata);
425+
struct bundle_priv *pbundle =
426+
container_of(&bundle->hdr, struct bundle_priv, bundle);
427+
428+
lockdep_assert_held(&bundle->ufile->device->disassociate_srcu);
429+
430+
return srcu_dereference(pbundle->method_elm->handler,
431+
&bundle->ufile->device->disassociate_srcu);
432+
}
433+
434+
int _ib_copy_validate_udata_in(struct ib_udata *udata, void *req,
435+
size_t kernel_size, size_t minimum_size)
436+
{
437+
int err;
438+
439+
if (udata->inlen < minimum_size) {
440+
ibdev_dbg(
441+
rdma_udata_to_dev(udata),
442+
"System call driver input udata too small (%zu < %zu) for ioctl %ps called by %pSR\n",
443+
udata->inlen, minimum_size,
444+
uverbs_get_handler_fn(udata),
445+
__builtin_return_address(0));
446+
return -EINVAL;
447+
}
448+
449+
err = copy_struct_from_user(req, kernel_size, udata->inbuf,
450+
udata->inlen);
451+
if (err) {
452+
if (err == -E2BIG) {
453+
ibdev_dbg(
454+
rdma_udata_to_dev(udata),
455+
"System call driver input udata not zero from %zu -> %zu for ioctl %ps called by %pSR\n",
456+
minimum_size, udata->inlen,
457+
uverbs_get_handler_fn(udata),
458+
__builtin_return_address(0));
459+
return -EOPNOTSUPP;
460+
}
461+
ibdev_dbg(
462+
rdma_udata_to_dev(udata),
463+
"System call driver input udata EFAULT for ioctl %ps called by %pSR\n",
464+
uverbs_get_handler_fn(udata),
465+
__builtin_return_address(0));
466+
return err;
467+
}
468+
return 0;
469+
}
470+
EXPORT_SYMBOL(_ib_copy_validate_udata_in);
471+
472+
int _ib_copy_validate_udata_cm_fail(struct ib_udata *udata, u64 req_cm,
473+
u64 valid_cm)
474+
{
475+
ibdev_dbg(
476+
rdma_udata_to_dev(udata),
477+
"System call driver input udata has unsupported comp_mask %llx & ~%llx = %llx for ioctl %ps called by %pSR\n",
478+
req_cm, valid_cm, req_cm & ~valid_cm,
479+
uverbs_get_handler_fn(udata), __builtin_return_address(0));
480+
return -EOPNOTSUPP;
481+
}
482+
EXPORT_SYMBOL(_ib_copy_validate_udata_cm_fail);
483+
484+
int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len)
485+
{
486+
size_t copy_len;
487+
488+
/* 0 length copy_len is a NOP for copy_to_user() and doesn't fail. */
489+
copy_len = min(len, udata->outlen);
490+
if (copy_to_user(udata->outbuf, src, copy_len))
491+
goto err_fault;
492+
if (copy_len < udata->outlen) {
493+
if (clear_user(udata->outbuf + copy_len,
494+
udata->outlen - copy_len))
495+
goto err_fault;
496+
}
497+
return 0;
498+
err_fault:
499+
ibdev_dbg(
500+
rdma_udata_to_dev(udata),
501+
"System call driver out udata has EFAULT (%zu into %zu) for ioctl %ps called by %pSR\n",
502+
len, udata->outlen, uverbs_get_handler_fn(udata),
503+
__builtin_return_address(0));
504+
return -EFAULT;
505+
}
506+
EXPORT_SYMBOL(_ib_respond_udata);
507+
#endif

drivers/infiniband/core/uverbs.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,41 @@ int uverbs_dealloc_mw(struct ib_mw *mw);
229229
void ib_uverbs_detach_umcast(struct ib_qp *qp,
230230
struct ib_uqp_object *uobj);
231231

232+
struct bundle_alloc_head {
233+
struct_group_tagged(bundle_alloc_head_hdr, hdr,
234+
struct bundle_alloc_head *next;
235+
);
236+
u8 data[];
237+
};
238+
239+
struct bundle_priv {
240+
/* Must be first */
241+
struct bundle_alloc_head_hdr alloc_head;
242+
struct bundle_alloc_head *allocated_mem;
243+
size_t internal_avail;
244+
size_t internal_used;
245+
246+
struct radix_tree_root *radix;
247+
const struct uverbs_api_ioctl_method *method_elm;
248+
void __rcu **radix_slots;
249+
unsigned long radix_slots_len;
250+
u32 method_key;
251+
252+
struct ib_uverbs_attr __user *user_attrs;
253+
struct ib_uverbs_attr *uattrs;
254+
255+
DECLARE_BITMAP(uobj_finalize, UVERBS_API_ATTR_BKEY_LEN);
256+
DECLARE_BITMAP(spec_finalize, UVERBS_API_ATTR_BKEY_LEN);
257+
DECLARE_BITMAP(uobj_hw_obj_valid, UVERBS_API_ATTR_BKEY_LEN);
258+
259+
/*
260+
* Must be last. bundle ends in a flex array which overlaps
261+
* internal_buffer.
262+
*/
263+
struct uverbs_attr_bundle_hdr bundle;
264+
u64 internal_buffer[32];
265+
};
266+
232267
long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
233268

234269
struct ib_uverbs_flow_spec {

drivers/infiniband/core/uverbs_ioctl.c

Lines changed: 0 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -35,54 +35,6 @@
3535
#include "rdma_core.h"
3636
#include "uverbs.h"
3737

38-
struct bundle_alloc_head {
39-
struct_group_tagged(bundle_alloc_head_hdr, hdr,
40-
struct bundle_alloc_head *next;
41-
);
42-
u8 data[];
43-
};
44-
45-
struct bundle_priv {
46-
/* Must be first */
47-
struct bundle_alloc_head_hdr alloc_head;
48-
struct bundle_alloc_head *allocated_mem;
49-
size_t internal_avail;
50-
size_t internal_used;
51-
52-
struct radix_tree_root *radix;
53-
const struct uverbs_api_ioctl_method *method_elm;
54-
void __rcu **radix_slots;
55-
unsigned long radix_slots_len;
56-
u32 method_key;
57-
58-
struct ib_uverbs_attr __user *user_attrs;
59-
struct ib_uverbs_attr *uattrs;
60-
61-
DECLARE_BITMAP(uobj_finalize, UVERBS_API_ATTR_BKEY_LEN);
62-
DECLARE_BITMAP(spec_finalize, UVERBS_API_ATTR_BKEY_LEN);
63-
DECLARE_BITMAP(uobj_hw_obj_valid, UVERBS_API_ATTR_BKEY_LEN);
64-
65-
/*
66-
* Must be last. bundle ends in a flex array which overlaps
67-
* internal_buffer.
68-
*/
69-
struct uverbs_attr_bundle_hdr bundle;
70-
u64 internal_buffer[32];
71-
};
72-
73-
uverbs_api_ioctl_handler_fn uverbs_get_handler_fn(struct ib_udata *udata)
74-
{
75-
struct uverbs_attr_bundle *bundle =
76-
rdma_udata_to_uverbs_attr_bundle(udata);
77-
struct bundle_priv *pbundle =
78-
container_of(&bundle->hdr, struct bundle_priv, bundle);
79-
80-
lockdep_assert_held(&bundle->ufile->device->disassociate_srcu);
81-
82-
return srcu_dereference(pbundle->method_elm->handler,
83-
&bundle->ufile->device->disassociate_srcu);
84-
}
85-
8638
/*
8739
* Each method has an absolute minimum amount of memory it needs to allocate,
8840
* 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,
860812
pbundle->uobj_hw_obj_valid);
861813
}
862814
EXPORT_SYMBOL(uverbs_finalize_uobj_create);
863-
864-
int _ib_copy_validate_udata_in(struct ib_udata *udata, void *req,
865-
size_t kernel_size, size_t minimum_size)
866-
{
867-
int err;
868-
869-
if (udata->inlen < minimum_size) {
870-
ibdev_dbg(
871-
rdma_udata_to_dev(udata),
872-
"System call driver input udata too small (%zu < %zu) for ioctl %ps called by %pSR\n",
873-
udata->inlen, minimum_size,
874-
uverbs_get_handler_fn(udata),
875-
__builtin_return_address(0));
876-
return -EINVAL;
877-
}
878-
879-
err = copy_struct_from_user(req, kernel_size, udata->inbuf,
880-
udata->inlen);
881-
if (err) {
882-
if (err == -E2BIG) {
883-
ibdev_dbg(
884-
rdma_udata_to_dev(udata),
885-
"System call driver input udata not zero from %zu -> %zu for ioctl %ps called by %pSR\n",
886-
minimum_size, udata->inlen,
887-
uverbs_get_handler_fn(udata),
888-
__builtin_return_address(0));
889-
return -EOPNOTSUPP;
890-
}
891-
ibdev_dbg(
892-
rdma_udata_to_dev(udata),
893-
"System call driver input udata EFAULT for ioctl %ps called by %pSR\n",
894-
uverbs_get_handler_fn(udata),
895-
__builtin_return_address(0));
896-
return err;
897-
}
898-
return 0;
899-
}
900-
EXPORT_SYMBOL(_ib_copy_validate_udata_in);
901-
902-
int _ib_copy_validate_udata_cm_fail(struct ib_udata *udata, u64 req_cm,
903-
u64 valid_cm)
904-
{
905-
ibdev_dbg(
906-
rdma_udata_to_dev(udata),
907-
"System call driver input udata has unsupported comp_mask %llx & ~%llx = %llx for ioctl %ps called by %pSR\n",
908-
req_cm, valid_cm, req_cm & ~valid_cm,
909-
uverbs_get_handler_fn(udata), __builtin_return_address(0));
910-
return -EOPNOTSUPP;
911-
}
912-
EXPORT_SYMBOL(_ib_copy_validate_udata_cm_fail);
913-
914-
int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len)
915-
{
916-
size_t copy_len;
917-
918-
/* 0 length copy_len is a NOP for copy_to_user() and doesn't fail. */
919-
copy_len = min(len, udata->outlen);
920-
if (copy_to_user(udata->outbuf, src, copy_len))
921-
goto err_fault;
922-
if (copy_len < udata->outlen) {
923-
if (clear_user(udata->outbuf + copy_len,
924-
udata->outlen - copy_len))
925-
goto err_fault;
926-
}
927-
return 0;
928-
err_fault:
929-
ibdev_dbg(
930-
rdma_udata_to_dev(udata),
931-
"System call driver out udata has EFAULT (%zu into %zu) for ioctl %ps called by %pSR\n",
932-
len, udata->outlen, uverbs_get_handler_fn(udata),
933-
__builtin_return_address(0));
934-
return -EFAULT;
935-
}
936-
EXPORT_SYMBOL(_ib_respond_udata);

0 commit comments

Comments
 (0)