mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
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: 1de9287ece ("RDMA: Add ib_copy_validate_udata_in()")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
This commit is contained in:
parent
01f99f8c4a
commit
7122ff9606
|
|
@ -422,12 +422,10 @@ 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,
|
||||
return srcu_dereference(bundle->method_elm->handler,
|
||||
&bundle->ufile->device->disassociate_srcu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,6 @@ struct bundle_priv {
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -397,13 +397,13 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
struct uverbs_attr_bundle *bundle =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs);
|
||||
unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey;
|
||||
unsigned int destroy_bkey = bundle->method_elm->destroy_bkey;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
/* See uverbs_disassociate_api() */
|
||||
handler = srcu_dereference(
|
||||
pbundle->method_elm->handler,
|
||||
bundle->method_elm->handler,
|
||||
&pbundle->bundle.ufile->device->disassociate_srcu);
|
||||
if (!handler)
|
||||
return -EIO;
|
||||
|
|
@ -421,12 +421,12 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
}
|
||||
|
||||
/* User space did not provide all the mandatory attributes */
|
||||
if (unlikely(!bitmap_subset(pbundle->method_elm->attr_mandatory,
|
||||
if (unlikely(!bitmap_subset(bundle->method_elm->attr_mandatory,
|
||||
pbundle->bundle.attr_present,
|
||||
pbundle->method_elm->key_bitmap_len)))
|
||||
bundle->method_elm->key_bitmap_len)))
|
||||
return -EINVAL;
|
||||
|
||||
if (pbundle->method_elm->has_udata)
|
||||
if (bundle->method_elm->has_udata)
|
||||
uverbs_fill_udata(bundle, &pbundle->bundle.driver_udata,
|
||||
UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT);
|
||||
else
|
||||
|
|
@ -451,7 +451,7 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
* assume that the driver wrote to its UHW_OUT and flag userspace
|
||||
* appropriately.
|
||||
*/
|
||||
if (!ret && pbundle->method_elm->has_udata) {
|
||||
if (!ret && bundle->method_elm->has_udata) {
|
||||
const struct uverbs_attr *attr =
|
||||
uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);
|
||||
|
||||
|
|
@ -472,7 +472,7 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
|
||||
static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
|
||||
{
|
||||
unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len;
|
||||
unsigned int key_bitmap_len = pbundle->bundle.method_elm->key_bitmap_len;
|
||||
struct uverbs_attr_bundle *bundle =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
struct bundle_alloc_head *memblock;
|
||||
|
|
@ -560,7 +560,7 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
|
|||
}
|
||||
|
||||
/* Space for the pbundle->bundle.attrs flex array */
|
||||
pbundle->method_elm = method_elm;
|
||||
pbundle->bundle.method_elm = method_elm;
|
||||
pbundle->method_key = attrs_iter.index;
|
||||
pbundle->bundle.ufile = ufile;
|
||||
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,
|
|||
pbundle->radix_slots_len = radix_tree_chunk_size(&attrs_iter);
|
||||
pbundle->user_attrs = user_attrs;
|
||||
|
||||
pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len *
|
||||
sizeof(*container_of(&pbundle->bundle,
|
||||
struct uverbs_attr_bundle, hdr)->attrs),
|
||||
sizeof(*pbundle->internal_buffer));
|
||||
pbundle->internal_used = ALIGN(
|
||||
pbundle->bundle.method_elm->key_bitmap_len *
|
||||
sizeof(*container_of(&pbundle->bundle,
|
||||
struct uverbs_attr_bundle, hdr)
|
||||
->attrs),
|
||||
sizeof(*pbundle->internal_buffer));
|
||||
memset(pbundle->bundle.attr_present, 0,
|
||||
sizeof(pbundle->bundle.attr_present));
|
||||
memset(pbundle->uobj_finalize, 0, sizeof(pbundle->uobj_finalize));
|
||||
|
|
|
|||
|
|
@ -635,6 +635,7 @@ struct uverbs_attr_bundle {
|
|||
struct ib_uverbs_file *ufile;
|
||||
struct ib_ucontext *context;
|
||||
struct ib_uobject *uobject;
|
||||
const struct uverbs_api_ioctl_method *method_elm;
|
||||
DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN);
|
||||
);
|
||||
struct uverbs_attr attrs[];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user