RDMA/core: Clear out the udata before error unwind

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: c4367a2635 ("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>
This commit is contained in:
Jason Gunthorpe 2019-05-21 17:55:22 +00:00
parent 619122be3d
commit 6875cb175c
3 changed files with 19 additions and 6 deletions

View 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.

View 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);

View 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;
}