RDMA/core: Clear out the udata before error unwind
authorJason Gunthorpe <jgg@mellanox.com>
Tue, 21 May 2019 17:55:22 +0000 (17:55 +0000)
committerJason Gunthorpe <jgg@mellanox.com>
Mon, 27 May 2019 17:35:26 +0000 (14:35 -0300)
The core code should not pass a udata to the driver destroy function that
contains the input from the create command. Otherwise the driver will
attempt to interpret the create udata as destroy udata, and at least in
the case of EFA, will leak resources.

Zero this stuff out before invoking destroy.

Reported-by: Leon Romanovsky <leonro@mellanox.com>
Fixes: c4367a26357b ("IB: Pass uverbs_attr_bundle down ib_x destroy path")
Reviewed-by: Gal Pressman <galpress@amazon.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_std_types_mr.c

index 5445323..e63fbda 100644 (file)
@@ -110,6 +110,8 @@ int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
 void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 
+struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs);
+
 /*
  * This is the runtime description of the uverbs API, used by the syscall
  * machinery to validate and dispatch calls.
index 5a3a178..a9b32eb 100644 (file)
@@ -174,6 +174,17 @@ static int uverbs_request_finish(struct uverbs_req_iter *iter)
        return 0;
 }
 
+/*
+ * When calling a destroy function during an error unwind we need to pass in
+ * the udata that is sanitized of all user arguments. Ie from the driver
+ * perspective it looks like no udata was passed.
+ */
+struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+{
+       attrs->driver_udata = (struct ib_udata){};
+       return &attrs->driver_udata;
+}
+
 static struct ib_uverbs_completion_event_file *
 _ib_uverbs_lookup_comp_file(s32 fd, struct uverbs_attr_bundle *attrs)
 {
@@ -441,7 +452,7 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(uobj, attrs);
 
 err_copy:
-       ib_dealloc_pd_user(pd, &attrs->driver_udata);
+       ib_dealloc_pd_user(pd, uverbs_get_cleared_udata(attrs));
        pd = NULL;
 err_alloc:
        kfree(pd);
@@ -644,7 +655,7 @@ err_copy:
        }
 
 err_dealloc_xrcd:
-       ib_dealloc_xrcd(xrcd, &attrs->driver_udata);
+       ib_dealloc_xrcd(xrcd, uverbs_get_cleared_udata(attrs));
 
 err:
        uobj_alloc_abort(&obj->uobject, attrs);
@@ -767,7 +778,7 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(uobj, attrs);
 
 err_copy:
-       ib_dereg_mr_user(mr, &attrs->driver_udata);
+       ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs));
 
 err_put:
        uobj_put_obj_read(pd);
@@ -2964,7 +2975,7 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 
 err_copy:
-       ib_destroy_wq(wq, &attrs->driver_udata);
+       ib_destroy_wq(wq, uverbs_get_cleared_udata(attrs));
 err_put_cq:
        uobj_put_obj_read(cq);
 err_put_pd:
@@ -3464,7 +3475,7 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 
 err_copy:
-       ib_destroy_srq_user(srq, &attrs->driver_udata);
+       ib_destroy_srq_user(srq, uverbs_get_cleared_udata(attrs));
 
 err_free:
        kfree(srq);
index 610d3b9..997f7a3 100644 (file)
@@ -148,7 +148,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(
        return 0;
 
 err_dereg:
-       ib_dereg_mr_user(mr, &attrs->driver_udata);
+       ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs));
 
        return ret;
 }