RDMA/core: Fix rereg_mr use-after-free race
When a driver creates a new MR during rereg_user_mr, a race window
exists between rdma_alloc_commit_uobject() for the new MR and the point
where the code reads that MR to populate the response keys.
A concurrent rereg_mr or destroy_mr could destroy the MR in this window
and cause UAF in the first thread.
Racing flow between two rereg_mr calls:
CPU0 CPU1
---- ----
rereg_user_mr(mr_handle)
uobj_get_write(mr_handle) -> mr0
mr1 = driver→rereg()
rdma_alloc_commit_uobject(mr1)
// mr1 replaced mr0 and is unlocked
uobj_put_destroy(mr0)
rereg_user_mr(mr_handle)
uobj_get_write(mr_handle) -> mr1
mr2 = driver→rereg()
rdma_alloc_commit_uobject(mr2)
// mr2 replaced mr1 and is unlocked
uobj_put_destroy(mr1)
// Destroys mr1!
resp.lkey = mr1->lkey; // UAF - mr1 was freed!
resp.rkey = mr1->rkey; // UAF - mr1 was freed!
Fix by storing lkey/rkey in local variables before the new MR is
unlocked and using the local variables to set the user response.
Fixes: 6e0954b11c ("RDMA/uverbs: Allow drivers to create a new HW object during rereg_mr")
Link: https://patch.msgid.link/r/20260427-security-bug-fixes-v3-4-4621fa52de0e@nvidia.com
Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
Reviewed-by: Maher Sanalla <msanalla@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
master
parent
610771c62e
commit
1f3b337af2
|
|
@ -778,6 +778,7 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
|
|||
struct ib_pd *orig_pd;
|
||||
struct ib_pd *new_pd;
|
||||
struct ib_mr *new_mr;
|
||||
u32 lkey, rkey;
|
||||
|
||||
ret = uverbs_request(attrs, &cmd, sizeof(cmd));
|
||||
if (ret)
|
||||
|
|
@ -846,6 +847,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
|
|||
new_mr->uobject = uobj;
|
||||
atomic_inc(&new_pd->usecnt);
|
||||
new_uobj->object = new_mr;
|
||||
lkey = new_mr->lkey;
|
||||
rkey = new_mr->rkey;
|
||||
|
||||
rdma_restrack_new(&new_mr->res, RDMA_RESTRACK_MR);
|
||||
rdma_restrack_set_name(&new_mr->res, NULL);
|
||||
|
|
@ -871,11 +874,13 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
|
|||
mr->iova = cmd.hca_va;
|
||||
mr->length = cmd.length;
|
||||
}
|
||||
lkey = mr->lkey;
|
||||
rkey = mr->rkey;
|
||||
}
|
||||
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
resp.lkey = mr->lkey;
|
||||
resp.rkey = mr->rkey;
|
||||
resp.lkey = lkey;
|
||||
resp.rkey = rkey;
|
||||
|
||||
ret = uverbs_response(attrs, &resp, sizeof(resp));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue