Re: use-after-free in srpt_enable_tpg()

From: Bart Van Assche
Date: Sun Jul 03 2022 - 10:55:12 EST


On 7/2/22 19:11, Hillf Danton wrote:
On Sat, 2 Jul 2022 15:26:33 -0700 Bart Van Assche wrote:
As long as a session is live the ch->qp pointer may be
dereferenced. The sdev->pd pointer is stored in the pd member of struct
ib_qp and hence may be dereferenced by any function that uses ch->qp.

If it is still an issue after ib_dealloc_pd(sdev->pd) then it goes beyond the
aperture of my proposal and needs another fix.

Hillf

+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -3235,6 +3235,8 @@ static void srpt_remove_one(struct ib_de
ib_set_client_data(device, &srpt_client, NULL);
+ /* make sdev survive ib_dealloc_pd(sdev->pd); */
+ atomic_inc(&sdev->port_refcount);
/*
* Unregistering a target must happen after destroying sdev->cm_id
* such that no new SRP_LOGIN_REQ information units can arrive while
@@ -3250,6 +3252,9 @@ static void srpt_remove_one(struct ib_de
srpt_free_srq(sdev);
ib_dealloc_pd(sdev->pd);
+
+ if (0 == atomic_dec_return(&sdev->port_refcount))
+ kfree(sdev);
}
static struct ib_client srpt_client = {

Do you perhaps want to combine the above patch with the previous patch? I don't think that any reference counting scheme can fix all use-after-free issues related to srpt_remove_one(). Immediately after srpt_remove_one() returns the caller of this function calls ib_device_put() and ib_client_put(). These functions free data structures that can be reached from the pointers that are stored in struct ib_qp. Holding a reference on struct ib_device as long as any session is live would allow to remove the while-loop from srpt_release_sport(). However, I'm not sure that would make a significant difference since there is a similar while-loop in one of the callers of srpt_remove_one() (disable_device() in the RDMA core).

Bart.