Message ID | 55CA09E5.2070208@dev.mellanox.co.il (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
On 08/11/2015 07:42 AM, Sagi Grimberg wrote: > [PATCH] IB/srp: Fix possible protection fault > > srp_destroy_qp is designed to indicate we are safe to continue with > freeing the channel resources by modifying the qp error state, > posting a dummy wr on the queue-pair and waiting for it to flush. > This also holds for the channel registration pool as we are unmapping > the memory region when handling a scsi response. Destroying the > channel registration pool before we make sure we processed all the > inflight IO might introduce a use-after-free of the registration pool. > > This use-after-free is demonstrated in the stack trace below where > srp is trying to unmap a used FMR after the fmr_pool was already destroyed. > > Reported-by: Eliott Kespi <eliottk@mellanox.com> > Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Please consider Cc-ing "stable" for this patch. Anyway, Reviewed-by: Bart Van Assche <bvanassche@sandisk.com> > Sorry for the mixup. Does this patch make more sense? Thank you for the quick respin. By posting this second patch quickly you saved me considerable time. I was going to verify whether any upstream patches were missing from the distro kernel that was used in your tests but this second description makes it clear that scsi_remove_host() was not involved in this crash. Bart. -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 3a1514c..b220856 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -546,6 +546,17 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch) if (ret) goto err_qp; + if (ch->qp) + srp_destroy_qp(ch); + if (ch->recv_cq) + ib_destroy_cq(ch->recv_cq); + if (ch->send_cq) + ib_destroy_cq(ch->send_cq); + + ch->qp = qp; + ch->recv_cq = recv_cq; + ch->send_cq = send_cq; + if (dev->use_fast_reg && dev->has_fr) { fr_pool = srp_alloc_fr_pool(target); if (IS_ERR(fr_pool)) { @@ -570,17 +581,6 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch) ch->fmr_pool = fmr_pool; } - if (ch->qp) - srp_destroy_qp(ch); - if (ch->recv_cq) - ib_destroy_cq(ch->recv_cq); - - ch->qp = qp; - ch->recv_cq = recv_cq; - ch->send_cq = send_cq; - kfree(init_attr); return 0; --