]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/core: Do not read wild stack memory in uverbs_get_handler_fn()
authorJason Gunthorpe <jgg@nvidia.com>
Wed, 13 May 2026 15:00:16 +0000 (12:00 -0300)
committerLeon Romanovsky <leon@kernel.org>
Tue, 19 May 2026 22:32:48 +0000 (19:32 -0300)
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: 1de9287ece44 ("RDMA: Add ib_copy_validate_udata_in()")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
drivers/infiniband/core/ib_core_uverbs.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_ioctl.c
include/rdma/uverbs_ioctl.h

index 685030e0c60fd0e6a8d1e99df34afbdfbd773a88..8a0e6fa2a528372f8bb1abd983445e3a74eb83c6 100644 (file)
@@ -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);
 }
 
index a74a2dff1301ed366704891351167d98bde0dcd8..f2e192b51e609cb59b166914088ecea45ead2120 100644 (file)
@@ -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;
index 33feb88d652b6a1bc396b2d8e3d03c88e0bdc379..2552a7efe2fbe2145ab227966ac6ec7623c54354 100644 (file)
@@ -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));
index e2af17da3e32ceb798521a5279787123e129e641..c89428030d61aebf20510fcc6cf14d3a5f2bdab6 100644 (file)
@@ -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[];