Skip to content

Commit

Permalink
IB/hfi1: On error, fix use after free during user context setup
Browse files Browse the repository at this point in the history
During base context setup, if setup_base_ctxt() fails, the context is
deallocated. This is incorrect because the context is referenced on
return, to notify any waiting subcontext.  If there are no subcontexts
the pointer will be invalid.

Reorganize the error path so that deallocate_ctxt() is called after all
the possible subcontexts have been notified.

Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Michael J. Ruhl authored and Doug Ledford committed Sep 27, 2017
1 parent 612601d commit b8f4273
Showing 1 changed file with 22 additions and 19 deletions.
41 changes: 22 additions & 19 deletions drivers/infiniband/hw/hfi1/file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -930,15 +930,8 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
switch (ret) {
case 0:
ret = setup_base_ctxt(fd, uctxt);
if (uctxt->subctxt_cnt) {
/*
* Base context is done (successfully or not), notify
* anybody using a sub-context that is waiting for
* this completion.
*/
clear_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
wake_up(&uctxt->wait);
}
if (ret)
deallocate_ctxt(uctxt);
break;
case 1:
ret = complete_subctxt(fd);
Expand Down Expand Up @@ -1305,38 +1298,48 @@ static int setup_base_ctxt(struct hfi1_filedata *fd,
/* Now allocate the RcvHdr queue and eager buffers. */
ret = hfi1_create_rcvhdrq(dd, uctxt);
if (ret)
return ret;
goto done;

ret = hfi1_setup_eagerbufs(uctxt);
if (ret)
goto setup_failed;
goto done;

/* If sub-contexts are enabled, do the appropriate setup */
if (uctxt->subctxt_cnt)
ret = setup_subctxt(uctxt);
if (ret)
goto setup_failed;
goto done;

ret = hfi1_alloc_ctxt_rcv_groups(uctxt);
if (ret)
goto setup_failed;
goto done;

ret = init_user_ctxt(fd, uctxt);
if (ret)
goto setup_failed;
goto done;

user_init(uctxt);

/* Now that the context is set up, the fd can get a reference. */
fd->uctxt = uctxt;
hfi1_rcd_get(uctxt);

return 0;
done:
if (uctxt->subctxt_cnt) {
/*
* On error, set the failed bit so sub-contexts will clean up
* correctly.
*/
if (ret)
set_bit(HFI1_CTXT_BASE_FAILED, &uctxt->event_flags);

setup_failed:
/* Set the failed bit so sub-context init can do the right thing */
set_bit(HFI1_CTXT_BASE_FAILED, &uctxt->event_flags);
deallocate_ctxt(uctxt);
/*
* Base context is done (successfully or not), notify anybody
* using a sub-context that is waiting for this completion.
*/
clear_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
wake_up(&uctxt->wait);
}

return ret;
}
Expand Down

0 comments on commit b8f4273

Please sign in to comment.