Skip to content

Commit 7122ff9

Browse files
jgunthorperleon
authored andcommitted
RDMA/core: Do not read wild stack memory in uverbs_get_handler_fn()
Sashiko points out the legacy write path in ib_uverbs_write() does allocate a struct uverbs_attr_bundle, but it doesn't wrap it in a bundle_priv so downcasting here isn't safe. Instead lift the method_elm out of the bundle_priv and use it for the debug function. The legacy write path will leave it set as NULL since the write method_elm uses a different type. Cc: stable@vger.kernel.org Fixes: 1de9287 ("RDMA: Add ib_copy_validate_udata_in()") Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
1 parent 01f99f8 commit 7122ff9

4 files changed

Lines changed: 16 additions & 16 deletions

File tree

drivers/infiniband/core/ib_core_uverbs.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,10 @@ uverbs_api_ioctl_handler_fn uverbs_get_handler_fn(struct ib_udata *udata)
422422
{
423423
struct uverbs_attr_bundle *bundle =
424424
rdma_udata_to_uverbs_attr_bundle(udata);
425-
struct bundle_priv *pbundle =
426-
container_of(&bundle->hdr, struct bundle_priv, bundle);
427425

428426
lockdep_assert_held(&bundle->ufile->device->disassociate_srcu);
429427

430-
return srcu_dereference(pbundle->method_elm->handler,
428+
return srcu_dereference(bundle->method_elm->handler,
431429
&bundle->ufile->device->disassociate_srcu);
432430
}
433431

drivers/infiniband/core/uverbs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ struct bundle_priv {
244244
size_t internal_used;
245245

246246
struct radix_tree_root *radix;
247-
const struct uverbs_api_ioctl_method *method_elm;
248247
void __rcu **radix_slots;
249248
unsigned long radix_slots_len;
250249
u32 method_key;

drivers/infiniband/core/uverbs_ioctl.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -397,13 +397,13 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
397397
struct uverbs_attr_bundle *bundle =
398398
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
399399
size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs);
400-
unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey;
400+
unsigned int destroy_bkey = bundle->method_elm->destroy_bkey;
401401
unsigned int i;
402402
int ret;
403403

404404
/* See uverbs_disassociate_api() */
405405
handler = srcu_dereference(
406-
pbundle->method_elm->handler,
406+
bundle->method_elm->handler,
407407
&pbundle->bundle.ufile->device->disassociate_srcu);
408408
if (!handler)
409409
return -EIO;
@@ -421,12 +421,12 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
421421
}
422422

423423
/* User space did not provide all the mandatory attributes */
424-
if (unlikely(!bitmap_subset(pbundle->method_elm->attr_mandatory,
424+
if (unlikely(!bitmap_subset(bundle->method_elm->attr_mandatory,
425425
pbundle->bundle.attr_present,
426-
pbundle->method_elm->key_bitmap_len)))
426+
bundle->method_elm->key_bitmap_len)))
427427
return -EINVAL;
428428

429-
if (pbundle->method_elm->has_udata)
429+
if (bundle->method_elm->has_udata)
430430
uverbs_fill_udata(bundle, &pbundle->bundle.driver_udata,
431431
UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT);
432432
else
@@ -451,7 +451,7 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
451451
* assume that the driver wrote to its UHW_OUT and flag userspace
452452
* appropriately.
453453
*/
454-
if (!ret && pbundle->method_elm->has_udata) {
454+
if (!ret && bundle->method_elm->has_udata) {
455455
const struct uverbs_attr *attr =
456456
uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);
457457

@@ -472,7 +472,7 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
472472

473473
static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
474474
{
475-
unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len;
475+
unsigned int key_bitmap_len = pbundle->bundle.method_elm->key_bitmap_len;
476476
struct uverbs_attr_bundle *bundle =
477477
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
478478
struct bundle_alloc_head *memblock;
@@ -560,7 +560,7 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
560560
}
561561

562562
/* Space for the pbundle->bundle.attrs flex array */
563-
pbundle->method_elm = method_elm;
563+
pbundle->bundle.method_elm = method_elm;
564564
pbundle->method_key = attrs_iter.index;
565565
pbundle->bundle.ufile = ufile;
566566
pbundle->bundle.context = NULL; /* only valid if bundle has uobject */
@@ -569,10 +569,12 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
569569
pbundle->radix_slots_len = radix_tree_chunk_size(&attrs_iter);
570570
pbundle->user_attrs = user_attrs;
571571

572-
pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len *
573-
sizeof(*container_of(&pbundle->bundle,
574-
struct uverbs_attr_bundle, hdr)->attrs),
575-
sizeof(*pbundle->internal_buffer));
572+
pbundle->internal_used = ALIGN(
573+
pbundle->bundle.method_elm->key_bitmap_len *
574+
sizeof(*container_of(&pbundle->bundle,
575+
struct uverbs_attr_bundle, hdr)
576+
->attrs),
577+
sizeof(*pbundle->internal_buffer));
576578
memset(pbundle->bundle.attr_present, 0,
577579
sizeof(pbundle->bundle.attr_present));
578580
memset(pbundle->uobj_finalize, 0, sizeof(pbundle->uobj_finalize));

include/rdma/uverbs_ioctl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ struct uverbs_attr_bundle {
635635
struct ib_uverbs_file *ufile;
636636
struct ib_ucontext *context;
637637
struct ib_uobject *uobject;
638+
const struct uverbs_api_ioctl_method *method_elm;
638639
DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN);
639640
);
640641
struct uverbs_attr attrs[];

0 commit comments

Comments
 (0)