On 10/19/20 1:53 PM, Jason Gunthorpe wrote: > On Fri, Oct 16, 2020 at 12:01:48PM -0500, Bob Pearson wrote: >> >> +static struct ib_ah *get_ah_from_handle(struct rxe_qp *qp, u32 handle) >> +{ >> + struct ib_uverbs_file *ufile; >> + struct uverbs_api *uapi; >> + const struct uverbs_api_object *type; >> + struct ib_uobject *uobj; >> + >> + ufile = qp->ibqp.uobject->uevent.uobject.ufile; >> + uapi = ufile->device->uapi; >> + type = uapi_get_object(uapi, UVERBS_OBJECT_AH); >> + if (IS_ERR(type)) >> + return NULL; >> + uobj = rdma_lookup_get_uobject(type, ufile, (s64)handle, >> + UVERBS_LOOKUP_READ, NULL); >> + if (IS_ERR(uobj)) { >> + pr_warn("unable to lookup ah handle\n"); >> + return NULL; >> + } >> + >> + rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_READ); > > It can't be put and then return the data pointer, it is a use after free: > >> + return uobj->object; > >> @@ -562,11 +563,6 @@ static int init_send_wqe(struct rxe_qp *qp, const struct ib_send_wr *ibwr, >> >> init_send_wr(qp, &wqe->wr, ibwr); >> >> - if (qp_type(qp) == IB_QPT_UD || >> - qp_type(qp) == IB_QPT_SMI || >> - qp_type(qp) == IB_QPT_GSI) >> - memcpy(&wqe->av, &to_rah(ud_wr(ibwr)->ah)->av, sizeof(wqe->av)); > > It needs some kind of negotiated compat, can't just break userspace > like this > > Jason > 1st point. I get it. uobj->object contains the address of one of the ib_xxx verbs objects. Normally the driver never looks at this level but presumably has a kref on that object so it makes sense to look it up. Perhaps better would be: void *object; ... uobj = rdma_lookup_get_uobject(...); object = uobj->object; rdma_lookup_put_uobject(...); return (struct ib_ah *)object; Here the caller has created the ib_ah but has not yet destroyed it so it must hold a kref on it. 2nd point. I also get. This suggestion imagines that there will come a day when we can change the user API. May be a rare day but must happen occasionally. The current design is just plain wrong and needs to get fixed eventually. Thanks for looking at this. Bob